groovy removeAll closure not removing elements in list - groovy

I'm not sure how removeAll in groovy works, but I expected this to return [40289454470ea94601470ea977d00018]
def list = ['40289454470ea94601470ea977b20014', '40289454470ea94601470ea977d00018']
def list2 = ['40289454470ea94601470ea977b20014']
list.removeAll {
list2
}
println list
but instead it returns []
please enlighten :(

removeAll with a Closure removes every element that the closure returns true for
list2 coerces to true under groovy truth as it isn't empty so your code removes everything
Try
list1 -= list2

Instead of using removeAll closure, you should simply use the removeAll method.
list.removeAll {
list2
}
The way with closure to go :
list.removeAll {
list2.contains(it)
}
If list2 contains this element, then it's removed from list

Related

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(',|!')

How to print all values in foreach

Groovy for-each returns only one value.which is first value please check it once.how to print all values
def list = [1,2,3,4]
for(item in list){
return item
}
def list = [1,2,3,4]
for(item in list){
print item
}
return is completely different thing. it is used for a function/method to evaluate a value.
You return from the method during the very first iteration of the loop. The loop will never execute more than the first iteration for that reason.

Checking multiple lists for emptiness in Groovy

Let's say I've got three lists with objects
List<String> list1, list2, list3
What is the best way to do check whether any of them is not empty and do some action?
So far I came up with
if ([list1, list2, list3].any()) {
// do some action
}
But is there a way to omit if block at all?
I don't think there can be anything better than
if (list1 || list2 || list3) {
}
You want some kind of NotEmptyPredicate(l1, l2, l3).ifMatch { println 'hi' }, but it does not exist in standard library. Creating one is not worth.
One objective part of your question is about omitting the if block. This answer pertains to that. I don't recommend this for production code, nor do I claim this is the best way, which is subjective.
Generally, if statements can be "hidden" by using maps. (The context is a new static method on List, via Groovy's meta-programming):
List.metaClass.static.ifNotEmpty = { List<String>... lists ->
def resultMap = [:]
resultMap[true] = { Closure c -> c.call() }
resultMap[false] = { Closure c -> }
return resultMap[lists.any()]
}
Here are example usages... See this Q&A to understand the unusual syntax of ({ })
List<String> list1, list2, list3
list1 = []
list2 = null
list3 = []
list3 << "HELLO"
List.ifNotEmpty(list1, list2, list3) ({ println "test 1" })
list1 = []
list2 = null
list3 = []
List.ifNotEmpty(list1, list2, list3) ({ println "should not see this" })

Groovy: same parameters, different results

In the below code, x.test() returns [1,2].
So y = [1,2].
Yet f([1,2]) prints 1, but f(y) prints 2.
How do I write f(y) so it prints 1?
Perversely, f(z) prints 1, even though z = y.
def f = { Object... args -> println args.size(); };
class Test { Object[] test() { return [1,2]; } }
def x = new Test();
def y = x.test();
def z = [1,2];
f([1,2]); // 1
f(y); // 2
f(z); // 1
The problem is that y and z, while they appear to be the same, are actually of different types. y is an Object[] while z is an ArrayList<Integer>. Groovy handles arrays and lists differently, automatically coercing the former into a varargs parameter list, but not the latter.
println y.getClass(); // class [Ljava.lang.Object
println z.getClass(); // class java.util.ArrayList
As for a solution to your problem, either change your test() to return a List instead of an array:
class Test { List test() { return [1,2]; } }
or manually coerce the array into a list when you pass it to f:
f(y as List); // 1
The expression [1,2] in Groovy denotes an ArrayList with two members, Integer.valueOf(1) and Integer.valueOf(2). Thus when you call f([1,2]) Groovy creates a single-element array containing this ArrayList as its only item, and passes that array as the closure argument.
But x.test() is declared to return Object[] so the [1,2] ArrayList will be converted to a two element Object[] by the return. Thus y is already an Object[] and does not need to be boxed up in a varargs array to be passed to f.
You need to turn y back into a list, either by changing the return type of test() or by saying
f(y as List)
Conversely, you can use the spread operator
f(*z) // 2
which will extract the elements of the ArrayList and pass them as individual arguments to the call (which will then be packaged up into a varargs array as usual).
y is an instance of [Ljava.lang.Object whereas [1,2] and z are of instance of ArrayList
The Array has the size() == 2 and the ArrayLists count as one argument, but they contain two elements
Groovy does some type converting for you ;)

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