How to Iterate array of objects in groovy - groovy

How to loop the array of objects in groovy?
I have tried below logic and got the No such property error.
def map = [{asset_key = helloWorld}, {asset_key = Demo}]
for(key in map){
println(key.asset_key)
}
error:
Caught: groovy.lang.MissingPropertyException: No such property: asset_key for class: maingroovy.lang.MissingPropertyException: No such property: asset_key for class: mainat main.run(main.groovy:4)
expected output:
helloWorld
Demo

The code {asset_key = helloWorld} is not a Groovy key-value pair, it's a closure. Try this instead:
def map = [ asset_key1: 'helloWorld', asset_key2:'Demo']
println "map is: ${map}\n"
map.each { key, value ->
println "$key has value $value"
}
Running the above example will give you this result:
The following code will give your desired output:
def map = [ asset_key1: 'helloWorld', asset_key2:'Demo']
map.each { key, value ->
println value
}

Related

Groovy iterate over Map of maps

I have a groovy map which looks like below.
image_map = [:]
image_map = [obj_1: ['1','2'], obj_2: ['3','4']]
I want to iterate through all the values(for obj_1, iterate throuth the list values['1','2']) for each object and run a method from the object.
obj_1.method(1)
obj_1.method(2)
obj_2.method(3)
obj_2.method(4)
Depends why you want to do it, but you could grab the values and flatten them:
image_map.values().flatten().each {
println it
}
So with the added requirement in the comment, you could do:
image_map.collectMany { k, v -> v.collect { "${k}.method($it)" } }
.each { println it }
To print
obj_1.method(1)
obj_1.method(2)
obj_2.method(3)
obj_2.method(4)
Edit 2 with another requirement... Assuming the keys ARE the objects (and not strings):
def obj_1 = [method: { it -> "I am obj1 $it" }]
def obj_2 = [method: { it -> "I am obj2 $it" }]
image_map = [(obj_1): ['1','2'], (obj_2): ['3','4']]
image_map.collectMany { k, v -> v.collect { [object: k, param: it] } }
.each { println it.object.method(it.param) }
Prints:
I am obj1 1
I am obj1 2
I am obj2 3
I am obj2 4

Groovy object properties in map

Instead of having to declare all the properties in a map from an object like:
prop1: object.prop1
Can't you just drop the object in there like below somehow? Or what would be a proper way to achieve this?
results: [
object,
values: [
test: 'subject'
]
]
object.properties will give you a class as well
You should be able to do:
Given your POGO object:
class User {
String name
String email
}
def object = new User(name:'tim', email:'tim#tim.com')
Write a method to inspect the class and pull the non-synthetic properties from it:
def extractProperties(obj) {
obj.getClass()
.declaredFields
.findAll { !it.synthetic }
.collectEntries { field ->
[field.name, obj."$field.name"]
}
}
Then, map spread that into your result map:
def result = [
value: true,
*:extractProperties(object)
]
To give you:
['value':true, 'name':'tim', 'email':'tim#tim.com']
If you don't mind using a few libraries here's an option where you convert the object to json and then parse it back out as a map. I added mine to a baseObject which in your case object would extend.
class BaseObject {
Map asMap() {
def jsonSlurper = new groovy.json.JsonSlurperClassic()
Map map = jsonSlurper.parseText(this.asJson())
return map
}
String asJson(){
def jsonOutput = new groovy.json.JsonOutput()
String json = jsonOutput.toJson(this)
return json
}
}
Also wrote it without the json library originally. This is like the other answers but handles cases where the object property is a List.
class BaseObject {
Map asMap() {
Map map = objectToMap(this)
return map
}
def objectToMap(object){
Map map = [:]
for(item in object.class.declaredFields){
if(!item.synthetic){
if (object."$item.name".hasProperty('length')){
map."$item.name" = objectListToMap(object."$item.name")
}else if (object."$item.name".respondsTo('asMap')){
map << [ (item.name):object."$item.name"?.asMap() ]
} else{
map << [ (item.name):object."$item.name" ]
}
}
}
return map
}
def objectListToMap(objectList){
List list = []
for(item in objectList){
if (item.hasProperty('length')){
list << objectListToMap(item)
}else {
list << objectToMap(item)
}
}
return list
}
}
This seems to work well
*:object.properties

Concise way of assigning a map entry only if new value is not empty or null in Groovy

I have this piece of code all over my gradle file:
def itemA = getVar('ITEM_A')
if (itemA) {
envmap['itemA'] = itemA
}
def itemB = getVar('ITEM_B')
if (itemB) {
envmap['itemB'] = itemB
}
Is there a much concise way of assigning to a variable only if new value is not null or empty?
You could write a helper closure like so:
def envHelper = { map, vkey, mkey ->
getVar(vkey)?.with { v ->
envmap[mkey] = v
}
}
then, you can replace
def itemA = getVar('ITEM_A')
if (itemA) {
envmap['itemA'] = itemA
}
with
envHelper(envmap, 'ITEM_A', 'itemA')
Use collectEntries and findAll to get a Map.
//An example of keys corresponding to your query
def keyNameFromVarName(String varName){
varName.toLowerCase().replace('_','').substring(0,varName.length()-2)+
varName.substring(varName.length()-1,varName.length())
}
def varNames = ['ITEM_C', 'ITEM_D', 'ITEM_E', 'ITEM_F', 'ITEM_G', 'ITEM_H']
Map map = varNames.collectEntries{ [ (keyNameFromVarName(it)) : getVar(it) ] }.findAll{ k,v-> v }
First use collectEntries on the list object. Remember to put the generation of the map key inside parentheses or you will get a compilation error.
varNames.collectEntries{ [ (keyNameFromVarName(it)) : getVar(it) ] }
Then use findAll to get the entries where the value is not null. Define k,v as parameters to the closure for easy access to the value.
.findAll{ k,v-> v }

Why is HashMap#get() in a foreach loop returning null?

For groovy -v: Groovy Version: 1.8.6 JVM: 1.6.0_26 Vendor: Sun Microsystems Inc. OS: Linux:
def map = new HashMap()
def keyVariable = "a"
def valueVariable = "b"
map.put("${keyVariable}", valueVariable)
for (String key : map.keySet()) {
println map.get(key)
}
This prints null. Could someone explain why Groovy finds the key, but can't find the corresponding value by the same key?
The code in the question doesn't print null for me (Groovy 2.1.6)
After the edit, the issue is that Groovy templated Strings make really bad map keys
More idiomatic Groovy would be:
def map = [:]
def keyVariable = "a"
def valueVariable = "b"
map[ keyVariable ] = valueVariable
map.each { key, value ->
println value
}
// Or
map.keySet().each { key ->
println map[ key ]
}

using ExpandoMetaclass in groovy print result and null value also

the sample progame when i try to run using the expandometaclass technique it give me two output one the desired result second one "null" as output, from where null is picked up ?
class testA {
static def X(def var) {
Y(var)
}
static def Y(def var) {
println var
}
}
testA.metaClass.static.newMethod = {z_var -> X(z_var) }
println testA.newMethod("anish")
output:
anish
**null**
why this progranme also print null as output
The null is the return value from newMethod. In case you don't want this to be printed remove the println from your line
println testA.newMethod("anish")

Resources