I am trying to get the set values from closure in groovy:
myList(1, 2, 3).any { it > 2 }
myList(1, 2, 3).find { it > 2 }
So not able to figure out, which one to use and better.
any returns boolean - true if any of the elements on the list matches the closure condition, while find returns first element that meets the criteria in closure being passed.
If you need to know if there're elements matching certain criteria, use any, if you need only a single element (the first one) use, find, if you need all the elements that matches the closure passed use findAll.
Example:
assert [1, 2, 3].any { it > 1 }
assert [1, 2, 3].find { it > 1 } == 2
assert [1, 2, 3].findAll { it > 1 } == [2, 3]
Related
I do not understand iter().all. This code from the docs works:
let d = [2, 3, 4, 6, 8];
assert!(a.iter().all(|x| *x > 0));
Why does the one below not work?
for x in d.iter().all(|x| *x > 2) {
println!("{} is bigger than 2", x);
}
all tests that the given predicate holds true for all elements. It returns false as soon as it finds an element that does not match the predicate, or true if all elements match. It is not used to iterate over matching elements. You should probably use filter for that. See the Iterator::all documentation.
Here is my code:
def myclosey = {items ->
items + 1}
myclosey(1..3);
I expect 1 to be added to every element in the intrange. Instead, 1 is just added to the end of intrange,
so output is
[1,2,3,1]
Why?
IntRange is a list. So the plus operator appends an element to the list. The closure is being called on the range itself, not each element of the range.
If you wanted to add one to all of the elements, you could do (1..3).collect { it + 1 }, or use the syntax that #dmahpatro suggested.
Because you are passing in a range to the closure so you have to do:
def myclosey = {items ->
items*.plus(1) //Spread on the range
}
assert myclosey(1..3) == [2, 3, 4]
I have a collection and I'm wanting to find certain elements and transform them. I can do this in two closures but I was wondering if it is possible with only one?
def c = [1, 2, 3, 4]
def result = c.findAll {
it % 2 == 0
}
result = result.collect {
it /= 2
}
My true use case is with Gradle, I want to find a specific bunch of files and transform them to their fully-qualified package name.
You can use findResults:
def c = [1, 2, 3, 4]
c.findResults { i ->
i % 2 == 0 ? // if this is true
i / 2 : // return this
null // otherwise skip this one
}
Also, you will get [] in case none of the elements satisfies the criteria (closure)
The following Groovy code
lines = ['0','1','2','3','4','5']
println lines[1..lines.size()-1]
println lines[1..-1]
println lines[1..<lines.size()-1]
println lines[1..<-1]
println lines[1..<-2]
println lines[1..-2]
produces this output:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 0]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
Since -1 is the index of the last element in the list, the first two make sense (ranges in Groovy include the end element instead of omitting it as everywhere else in Java :-( )
Line #3 is the desired output (list without first and last element).
I'm worried about the output #4: Why do I get [1, 0] for 1..-1?
Also [1, 2, 3, 4, 5] for the range 1..<-2 seems wrong.
Why does that happen?
The best way to take all elements but the last one, in my opinion, is to use the take method:
def list = ['a', 'b', 'c']
assert list.take(list.size() - 1) == ['a', 'b']
It behaves properly in the corner case where size == 1:
def list = ['one']
assert list.take(list.size() - 1) == []
Though I'd prefer it to throw an exception in the case size == 0, but the behavior is not that bad:
def list = []
assert list.take(list.size() - 1) == []
You can also use list[0..<list.size()-1] (your third example) and it will behave the same except for the empty list, in which case it will throw an ArrayIndexOutOfBoundsException, but i think is not as readable as the take counterpart.
Another acceptable solution is using list[0..-2] (your last example), which i think looks much more elegant, but unfortunately breaks when size == 1 with an ArrayIndexOutOfBoundsException.
In your examples (i'll assume that you meant to use 0 as the starting index instead of 1 if you wanted to include all elements but the last one):
lines[0..lines.size()-1] is equivalent to lines[0..-1] because the getAt(Range) method of lists will treat ranges with negative indexes the same way asgetAt(Integer) does, i.e. as accessing the (list.size() + negativeIndex)'th element of the list. Therefore list[0..-1] is the same as saying "from first element to last" and it's the same as copying the list; and list[-1..0] is the same as "from last to first" and it's equivalent to list.reverse() :)
The problem with the other non-inclusive range example is that the non-inclusive ranges are being evaluated before the list access and they evaluate to an incorrect inclusive range. For example, 0..<-2 evaluates to 0..-1, and that's why it's returning all the elements. 0..<-1 evaluates to 0..0 and it returns only the first element.
Notice that the empty range is a special case. It's denoted as 0..<0 and it doesn't have an inclusive equivalent (so Groovy won't do any magic conversion here). And that's why list[0..<list.size()-1] works when size == 1 (the range evaluates to the empty range) while list[0..-2] doesn't :)
Maybe this has changed since epideman wrote his answer, but you can get the whole list without the last element with 0..<-1:
assert ["foo"][0..<-1] == []
assert ["foo", "bar"][0..<-1] == ["foo"]
assert ["foo", "bar", "baz"][0..<-1] == ["foo", "bar"]
// blows up if empty, here take is better
assert [][0..<-1] == [] // BOOM
// if you want null safe, use take
assert [].take(-1) == []
This is with groovy 2.2.1.
Since Groovy 2.4 you can use the init() method:
lines = ['0','1','2','3','4','5']
assert lines.init() == ['0','1','2','3','4']
How can I use Groovy to add an item to the beginning of a list?
list.add(0, myObject);
You can also read this for some other valuable examples:
http://groovy.codehaus.org/JN1015-Collections
Another option would be using the spread operator * which expands a list into its elements:
def list = [2, 3]
def element = 1
assert [element, *list] == [1, 2, 3]
Another alternative would be to put the element into a list and concatenate the two lists:
assert [element] + list == [1, 2, 3]
Caution!
From Groovy 2.5:
list.push( myObject )
Prior to Groovy 2.5 list.push appends ... but from 2.5/2.6 (not yet Beta) it will (it seems) prepend, "to align with Java"... indeed, java.util.Stack.push has always prepended.
In fact this push method does not belong to List, but to GDK 2.5 DefaultGroovyMethods, signature <T> public static boolean push(List<T> self, T value). However, because of Groovy syntax magic we shall write as above: list.push( myObject ).
def list = [4, 3, 2, 1, 0]
list.plus(0, 5)
assert list == [5, 4, 3, 2, 1, 0]
You can find more examples at this link