Groovy remove duplicate from list using unique function - string

I'm using soapui groovy script.
I want to remove the duplicate from a list, using the next code:
def myStr = "aaaa ; bbbb ; ccccc"
def myList = myStr.split(";")
myList = myList.unique()
but when i tun the code i get exception:
No signature of method: [Ljava.lang.String;.unique() is applicable for
argument types: () values: [] Possible solutions:
minus(java.lang.Object), minus(java.lang.Iterable),
minus([Ljava.lang.Object;), size(), use([Ljava.lang.Object;),
use(java.lang.Class, groovy.lang.Closure)

Use tokenize() instead of split() which returns an ArrayList as compared to split which return a String Array.
def myStr = "aaaa ; bbbb ; ccccc;"
def myList = myStr.tokenize(";")*.trim()
myList = myList.unique()
or use toList() if you are using split() or cast the String array to a Set.
However, based on the question you want to remove the duplicate items from list but I do not see any duplicate item. If you mean to remove duplicate strings from the list items then use:
myList = myList.unique().collect { it.toSet().join() }

Simple, .split() returns an array, you just need to convert it to a (Groovy) List. Any of the following will make the unique() method work.
def myList = myStr.split(";").collect()
or
def myList = (List)myStr.split(";")
or
def myList = myStr.split(";").toList()
If you cast it to a java.util.Set, it'll only keep unique values!
def myList = (Set)myStr.split(";")
Gotcha: Be careful though, the strings still contain the spaces!

Related

Create Map with CollectEntries in Groovy

I have the following list:
appList = [DevOpsApplication, 01.01.01]
I would like to create a map using collectEntries. I know that it refers to the current element of an iteration (shortcut for { it -> it }). Therefore, I tried to use the index:
def appMap = appList.collectEntries { [(it[0]):it[1]] }
However, this gives me:
[D:e, 0:1]
But I want [DevOpsApplication: 01.01.01]. Is there a way to do this?
Additionally, In future I would like this to expand to more than 2 elements (e.g. [DevOpsApplication, 01.01.01, AnotherDevOpsApplication, 02.02.02]) with the desired output of [DevOpsApplication: 01.01.01, AnotherDevOpsApplication: 02.02.02].
How will this be possible?
A very short version to do this would be:
def appList = ["DevOpsApplication", "01.01.01"]
def appMap = [appList].collectEntries() // XXX
assert appMap == [DevOpsApplication: "01.01.01"]
How does it work: the function collectEntries takes, is expected to return a map or a two element list. Your appList is already that. So put that in another list, call collectEntries on it. When no function is given to collectEntries it uses the identity function.
Bonus: what if appList has much more elements? You can use collate to build the tuples.
def appList = ["DevOpsApplication", "01.01.01", "Some", "More"]
def appMap = appList.collate(2).collectEntries() // XXX
assert appMap == [DevOpsApplication: "01.01.01", Some: "More"]
I also found another method. Groovy can convert the values of an Object array and convert them into a map with the toSpreadMap(). However, the array must have an even number of elements.
def appList = ['DevOpsApplication', '01.01.01']
def appMap = appList.toSpreadMap()
You're iterating element-by-element and (because your elements are String-typed) mapping 0 substrings to 1 substrings.
You can use this to skip one element in each iteration and map each element at even indices to the one after it:
def appList = ['DevOpsApplication', '01.01.01']
def appMap = (0..(appList.size()-1)).findAll{0 == it%2}
.collectEntries{[(appList[it]): appList[it+1]]}
That returns [DevOpsApplication:01.01.01] as expected.

Appending Elements to a List Creates List of List in Groovy

I am parsing each element of a list one by one.
def List1 = (String[]) Data[2].split(',')
Part of this list gives me a list with elements that contain a delimiter !.
List1 = [TEST1!01.01.01, TEST2!02.02.02]
I tried to iterate each element of this list and obtain a comma separated list.
def List2 = []
List1.each { List2.add(it.split('!'))}
However, the result was a list of list.
[[TEST1, 01.01.01], [TEST2, 02.02.02]]
Instead of [TEST1, 01.01.01, TEST2, 02.02.02].
How do I avoid this and obtain a list as shown above?
How about this?
def list1 = ['TEST1!01.01.01', 'TEST2!02.02.02']
println list1.collect{it.split('!')}.flatten()
When you do List2.add(it.split('!')), you are adding list to List2 instead of single string because .split() creates a list from string.
You should firstly create list by using .split() and than add each member of list to List2.
Here is solution:
def List1 = ["TEST1!01.01.01", "TEST2!02.02.02"]
​def List2 = []
List1.each { List1member ->
def subList = List1member.split('!')
subList.each { subListMember ->
List2.add(subListMember)
}
}
println(List2)​
split() returns a list. That is the reason why I got a list of list. I found that split() can carry process multiple delimiters as well when applied with an operator.
The following returns the desired output.
def List1 = (String[]) Data[2].split(',|!')

Make Strings In List Uppercase - Python 3

I'm in the process of learning python and with a practical example I've come across a problem I cant seem to find the solution for.
The error I get with the following code is
'list' object has to attribute 'upper'.
def to_upper(oldList):
newList = []
newList.append(oldList.upper())
words = ['stone', 'cloud', 'dream', 'sky']
words2 = (to_upper(words))
print (words2)
Since the upper() method is defined for string only and not for list, you should iterate over the list and uppercase each string in the list like this:
def to_upper(oldList):
newList = []
for element in oldList:
newList.append(element.upper())
return newList
This will solve the issue with your code, however there are shorter/more compact version if you want to capitalize an array of string.
map function map(f, iterable). In this case your code will look like this:
words = ['stone', 'cloud', 'dream', 'sky']
words2 = list(map(str.upper, words))
print (words2)
List comprehension [func(i) for i in iterable].In this case your code will look like this:
words = ['stone', 'cloud', 'dream', 'sky']
words2 = [w.upper() for w in words]
print (words2)
You can use the list comprehension notation and apply theupper method to each string in words:
words = ['stone', 'cloud', 'dream', 'sky']
words2 = [w.upper() for w in words]
Or alternatively use map to apply the function:
words2 = list(map(str.upper, words))
AFAIK, upper() method is implemented for strings only. You have to call it from each child of the list, and not from the list itself.
It's great that you're learning Python! In your example, you are trying to uppercase a list. If you think about it, that simply can't work. You have to uppercase the elements of that list. Additionally, you are only going to get an output from your function if you return a result at the end of the function. See the code below.
Happy learning!
def to_upper(oldList):
newList = []
for l in oldList:
newList.append(l.upper())
return newList
words = ['stone', 'cloud', 'dream', 'sky']
words2 = (to_upper(words))
print (words2)
Try it here!

Partitioning a string to get a list in Groovy

I have the following String :
def s="txtimgtxtvdd"
i want to extract a list from the String above as following
def l=["txt","img","txt","vdd"]
Each 3 consecutive letters is an item of list
You can use collate (and toList to split the string into a list of chars)
def part = 'txtimgtxtvdd'.toList().collate( 3 )*.join()
assert part == ['txt', 'img', 'txt', 'vdd']

Groovy String concatenation with null checks

Is there a better way to do this? Note: part1, part2 and part3 are string variables defined elsewhere (they can be null).
def list = [part1, part2, part3]
list.removeAll([null])
def ans = list.join()
The desired result is a concatenated string with null values left out.
You can do this:
def ans = [part1, part2, part3].findAll({it != null}).join()
You might be able to shrink the closure down to just {it} depending on how your list items will evaluate according to Groovy Truth, but this should make it a bit tighter.
Note: The GDK javadocs are a great resource.
If you use findAll with no parameters. It will return every "truthful" value, so this should work:
def ans = [part1, part2, part3].findAll().join()
Notice that findAll will filter out empty strings (because they are evaluated as false in a boolean context), but that doesn't matter in this case, as the empty strings don't add anything to join() :)
If this is a simplified question and you want to keep empty string values, you can use findResults{ it }.
Alternatively, you can do this as a fold operation with inject:
def ans = [part1, part2, part3].inject('') { result, element ->
result + (element ?: '')
}
This iterates the whole list and concatenates each successive element to a result, with logic to use the empty string for null elements.
You could use grep:
groovy:000> list = ['a', 'b', null, 'c']
===> [a, b, null, c]
groovy:000> list.grep {it != null}.join()
===> abc

Resources