I am trying to understand if the following Groovy syntax is correct:
String f() { return "Hello"}
String g() { return "World"}
Map myMap = [
a : f(),
b : g(),
]
String x = myMap['a']
String y = myMap['b']
assert x == "Hello"
assert y == "World"
The Groovy language reference documentation on maps is not clear in this regard:
http://docs.groovy-lang.org/latest/html/documentation/index.html#_maps
Yes it's correct. Your case is covered in the first example in the documentation.
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
Think of the syntax as something like this: [value: expression]
The keys a and b become strings (value) and the methods are called to evaluate the expressions.
Related
I would like to remove duplicates maps equal to some conditions, I have the maps below:
def map = [[name: "111F", invoice:"40",bilD:"aaaa", title:null],[name: "111F", invoice:"40",bilD:"aaaa",title:"something"],[name: "111F", invoice:"40",bilD:"bbbb",title:"something"]]
I tried with the code below to do that, but its not working
def newMap = map.unique {a, b -> (a.name == b.name && a.invoice == b.invoice && a.bilD == b.bilD)}
How can I get a map like below
[
[name: "111F", invoice:"40",bilD:"aaaa",title:"somethingOrNull"],[name: "111F", invoice:"40",bilD:"bbbb",title:"something"]
]
The easiest way I can think of is, add all the elements to a set, then transform the resulting set back to list (note, that your variable map actually contains a list).
The shortest way I can think of would be calling:
def newMap = (map as Set) as List
Collection.unique(Closure) behaves differently depending on the number of parameters in the closure. When the closure has one parameter it expects...
...a value used for comparison (either using
Comparable#compareTo(java.lang.Object) or
Object#equals(java.lang.Object)).
However, if the closure contains two arguments, as shown in your example, then the closure must return an integer...
...with 0 indicating the items are not unique
Strangely, the two-argument closure behavior seems to be in exact opposite of how it's described. Here's a working example:
def maps = [
[name: "111F", invoice:"40",bilD:"aaaa"],
[name: "111F", invoice:"40",bilD:"aaaa"],
[name: "111F", invoice:"40",bilD:"bbbb"]
]
assert maps.unique(false) {a, b ->
a.name == b.name && a.invoice == b.invoice && a.bilD == b.bilD ? 0 : 1
} == [['name':'111F', 'invoice':'40', 'bilD':'aaaa'], ['name':'111F', 'invoice':'40', 'bilD':'bbbb']]
However, in your case, you can simply use unique() without the closure:
assert maps.unique(false) == [['name':'111F', 'invoice':'40', 'bilD':'aaaa'], ['name':'111F', 'invoice':'40', 'bilD':'bbbb']]
I am currently trying to split a string 1128-2 so that I can have two separate values. For example, value1: 1128 and value2: 2, so that I can then use each value separately. I have tried split() but with no success. Is there a specific way Grails handles this, or a better way of doing it?
Try:
def (value1, value2) = '1128-2'.tokenize( '-' )
How are you calling split? It works like this:
def values = '1182-2'.split('-')
assert values[0] == '1182'
assert values[1] == '2'
def (value1, value2) = '1128-2'.split('-') should work.
Can anyone please try this in Groovy Console?
def (v, z) = '1128-2'.split('-')
assert v == '1128'
assert z == '2'
You can also do:
Integer a = '1182-2'.split('-')[0] as Integer
Integer b = '1182-2'.split('-')[1] as Integer
//a=1182 b=2
split doesn't work that way in groovy. you have to use tokenize...
See the docs:
http://groovy-lang.org/gdk.html#split()
dependencies {
compile ('org.springframework.kafka:spring-kafka-test:2.2.7.RELEASE') { dep ->
['org.apache.kafka:kafka_2.11','org.apache.kafka:kafka-clients'].each { i ->
def (g, m) = i.tokenize( ':' )
dep.exclude group: g , module: m
}
}
}
Hi I have a map like this :
[this:0, is:1, a:2, file:3, anotherkey:4, aa:5]
I wish I could find the key's given the value of a map. For example, if the value 5 is given I need to return aa from the map.
Is that possible?
I don't know if there's a direct method to get a key for a given value, but using Map#find to get a map entry and then get its value should be enough:
def keyForValue(map, value) {
map.find { it.value == value }?.key
}
def map = [a: 1, b: 2, c: 3]
assert keyForValue(map, 2) == 'b'
assert keyForValue(map, 42) == null
In general, maps don't need to have an order relation between their entries, but the default implementation for Groovy's literal maps is LinkedHashMap, which is ordered, so the keyForValue will always yield the first key for a value when using those maps.
There's no specific command for that.
Fortunately, as showed here, you can easily get the key(s) for a specific value in a map:
def myMap = [this:0, is:1, a:2, file:3, fix:4, aa:5]
def myValue = 5
You can do:
def myKey = myMap.find{ it.value == myValue }?.key
// 'aa'
If you want all the keys, do something like this:
def myMap = [this:0, is:1, a:2, file:3, fix:4, aa:5, bb:5]
def myValue = 5
def myKeys = []
myMap.findAll{ it.value == myValue }.each{myKeys << it?.key}
// ['aa', 'bb']
You could invert the map, like this:
Map m = [a: '1', b: '2']
Map mInvert = m.collectEntries { e -> [(e.value): e.key] }
assert mInvert == ['1':'a', '2':'b']
assert mInvert['2'] == 'b'
assert m['b'] == '2'
You'll probably have to iterate over the entry set yourself and try to find the entry with a matching value.
def expect = 5
def m = ['this':0, is:1, a:2, file:3, aa:5]
def r = m.collectMany{ k,v -> (v == expect) ? [k] : []}
// Result: [aa]
How can I convert a string like this
'[["dfd","ewer","errr","ggg"],["yyy","ttt","rrr","ggg"]]'
into a list?
I don't want to use GroovyShell().evaluate()
Thanks
You can use Eval.me like so:
String input = '[["dfd","ewer","errr","ggg"],["yyy","ttt","rrr","ggg"]]'
List output = Eval.me( input )
assert output.size() == 2
assert output*.size() == [ 4, 4 ]
(though of course, under the covers, Groovy just calls GroovyShell.evaluate())
Then for pure Groovy, there's JsonParser:
output = new groovy.json.JsonSlurper().parseText( input )
I have a couple questions on applying spread operator on range and map. Refer to code below, error lines are marked.
(1) "assert" works on the updated range, but why doesnt "println" print it?
(2) when we say "*range" groovy can figure out and extend the range. So why doesnt "map" work also, why do we need to say ":map" ?
def range = (1..3)
println range // prints: [1,2,3]
assert [0,1,2,3] == [0,*range] // works ok
println [0, *range] // error
def map = [a:1, b:2]
assert [a:1, b:2, c:3] == [c:3, *:map] // works ok
assert [a:1, b:2, c:3] == [c:3, *map] // error
When you call:
println [0, *range]
it is trying to call getAt on a property println. You need to wrap the list in braces to help the parser out:
println( [ 0, *range ] )
And for the second error, * in this form is the spread operator. It is used to spread Lists.
You have a map, so need to use the spread map operator *: (as you have seen)