Is it possible to do a conditional collectEntries like collect ?
Asked
Active
Viewed 9,675 times
4 Answers
9
It's not as succinct as Tim Yates's answer using findAll; but just for the record, you can use collectEntries
to do this:
[ a:1, b:2, c:3, d:4 ].collectEntries {
it.value > 2 ? [(it.key) : it.value] : [:] }
which evaluates to
[c:3, d:4]
Using "${it.key}" as done in this answer is an error, the key will end up being an instance of the GStringImpl class, not a String. The answer itself looks ok in the REPL but if you check what class it is, you can see it is wrong:
groovy:000> m = [ a:1, b:2, c:3, d:4 ]
===> [a:1, b:2, c:3, d:4]
groovy:000> m.collectEntries { ["${it.key}" : it.value ] }
===> [a:1, b:2, c:3, d:4]
groovy:000> _.keySet().each { println(it.class) }
class org.codehaus.groovy.runtime.GStringImpl
class org.codehaus.groovy.runtime.GStringImpl
class org.codehaus.groovy.runtime.GStringImpl
class org.codehaus.groovy.runtime.GStringImpl
===> [a, b, c, d]
Code trying to equate GroovyStrings to normal strings will evaluate to false even when the strings look identical, resulting in a hard-to-figure-out bug.

Nathan Hughes
- 94,330
- 19
- 181
- 276
-1
This should work:
[a:1, b:2, c:3, d:4].collectEntries {
if (it.value > 2)
["${it.key}": it.value]
}

Thermech
- 4,371
- 2
- 39
- 60
-
7Throws a NPE as is. You need an `else [:]` – Marty Neal Jun 04 '14 at 22:52
-1
it works now after adding else. thanks
[a:1, b:2, c:3, d:4].collectEntries {
if (it.value > 2){
["${it.key}": it.value]
}else{
[:]
}
}

CRB BELOUIZDAD
- 9
- 1
-
1this does not solve the issue pointed to by Nathan Hughes, the keys will be instances of `GStringImpl` and not a regular String. To use variables as map keys, just surround them with braces: `[(it.key): it.value]` – Onno Rouast Nov 09 '20 at 13:37