Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inline Conditional Map Literal in Groovy

Tags:

groovy

Working on some translation / mapping functionality using Maps/JsonBuilder in Groovy.

Is is possible (without creating extra code outside of the map literal creation) .. to conditionally include/exclude certain key/value pairs ? Some thing along the lines of the following ..

 def someConditional = true   

 def mapResult = 
        [
           "id":123,
           "somethingElse":[],
           if(someConditional){ return ["onlyIfConditionalTrue":true]}
        ]

Expected results: If someConditional if false, only 2 key/value pairs will exist in mapResult.

If someConditional if true, all 3 key/value pairs will exist.

Note that I'm sure it could be done if I create methods / and split things up.. for to keep things concise I would want to keep things inside of the map creation.

like image 995
vicsz Avatar asked Mar 12 '23 13:03

vicsz


2 Answers

You can help yourself with with:

[a:1, b:2].with{
    if (false) {
        c = 1
    }
    it
}

With a small helper:

Map newMap(m=[:], Closure c) {
    m.with c
    m
}

E.g.:

def m = newMap {
    a = 1
    b = 1
    if (true) {
        c = 1
    }
    if (false) {
        d = 1
    }
}

assert m.a == 1
assert m.b == 1
assert m.c == 1
assert !m.containsKey('d')

Or pass an initial map:

newMap(a:1, b:2) {
    if (true) {
        c = 1
    }
    if (false) {
        d = 1
    }
}

edit

Since Groovy 2.5, there is an alternative for with called tap. It works like with but does not return the return value from the closure, but the delegate. So this can be written as:

[a:1, b:2].tap{
    if (false) {
        c = 1
    }
}
like image 153
cfrick Avatar answered Apr 30 '23 15:04

cfrick


You could potentially map all false conditions to a common key (e.g. "/dev/null", "", etc) and then remove that key afterwards as part of a contract. Consider the following:

def condA = true   
def condB = false   
def condC = false   

def mapResult = 
[
   "id":123,
   "somethingElse":[],
   (condA ? "condA" : "") : "hello",
   (condB ? "condB" : "") : "abc",
   (condB ? "condC" : "") : "ijk",
]

// mandatory, arguably reasonable
mapResult.remove("")

assert 3 == mapResult.keySet().size()
assert 123 == mapResult["id"]
assert [] == mapResult["somethingElse"]
assert "hello" == mapResult["condA"]
like image 45
Michael Easter Avatar answered Apr 30 '23 15:04

Michael Easter