Groovy not in collection
GroovyGroovy Problem Overview
The groovy way to see if something is in a list is to use "in"
if('b' in ['a','b','c'])
However how do you nicely see if something is not in a collection?
if(!('g' in ['a','b','c']))
Seems messy and the "!" is hidden to the casual glance. Is there a more idiomatic groovy way to do this?
Thanks!
Groovy Solutions
Solution 1 - Groovy
Another way to write it is with contains
, e.g.
if (!['a', 'b', 'c'].contains('b'))
It saves the extra level of parentheses at the cost of replacing the operator with a method call.
Solution 2 - Groovy
I think there is no not in
pretty syntax, unfortunately. But you can use a helper variable to make it more readable:
def isMagicChar = ch in ['a', 'b', 'c']
if (!isMagicChar) ...
Or, in this case, you may use a regex :)
if (ch !=~ /[abc]/) ...
Solution 3 - Groovy
You can add new functions:
Object.metaClass.notIn = { Object collection ->
!(delegate in collection)
}
assert "2".notIn(['1', '2q', '3'])
assert !"2".notIn(['1', '2', '3'])
assert 2.notIn([1, 3])
assert !2.notIn([1, 2, 3])
assert 2.notIn([1: 'a', 3: 'b'])
assert !2.notIn([1: 'a', 2: 'b'])
Solution 4 - Groovy
More readable, I'm not sure:
assert ['a','b','c'].any{it == 'b'}
assert ['a','b','c'].every{it != 'g'}
For your example:
if (['a','b','c'].every{it != 'g'})
A few months ago, I suggested a new operator overloading ! (not operator). Now, maybe you can use any odd number of exclamations ;)
if(!!!('g' in ['a','b','c']))
Solution 5 - Groovy
Just for the sake of completeness, and for people reaching this thread post-2020, Groovy 3.0.0 introduced the !in
operator.
As per the OP example, it would be used like that:
if ('g' !in ['a','b','c'])
Solution 6 - Groovy
According to Grails documentation about creating criteria here, you can use something like this:
not {'in'("age",[18..65])}
In this example, you have a property named "age"
and you want to get rows that are NOT between 18 and 65. Of course, the [18..65]
part can be substituted with any list of values or range you need.
Solution 7 - Groovy
Regarding one of the original answers:
if (!['a', 'b', 'c'].contains('b'))
Somebody mentioned that it is easy to miss the ! because it's far from the method call. This can be solved by assigning the boolean result to a variable and just negate the variable.
def present = ['a', 'b', 'c'].contains('b')
if (!present) {
// do stuff
}
Solution 8 - Groovy
The contains(string) method is nice and simple to read if something is contained or not contained in the list to be checked against. Take a look the example below for more insight.
EXAMPLE
//Any data you are looking to filter
List someData = ['a', 'f', 'b', 'c', 'o', 'o']
//A filter/conditions to not match or match against
List myFilter = ['a', 'b', 'c']
//Some variables for this example
String filtered, unfiltered
//Loop the data and filter for not contains or contains
someData.each {
if (!myFilter.contains(it)){
unfiltered += it
} else {
filtered += it
}
}
assert unfiltered = "foo"
assert filtered = "abc"
CONTAINS( )
Parameters: text - a String to look for.
Returns: true if this string contains the given text
Solution 9 - Groovy
What about disjoint
?
def elements = [1, 2, 3]
def element = 4
assert elements.disjoint([element])
element = 1
assert !elements.disjoint([element])
Bonus : it stops iterating when an element match