So essentially I have something like this:
[a: ["c","d"], b: ["e","f"]]
The amount of items in each list is arbitrary. If there is only one item the list is no longer a list and it is a string.
I want to turn it into:
[ [a:"c", b:"e"], [a:"d",b:"f"] ]
I don't really care if the solution uses Groovy methods or not. Thanks for your help!
Using a SpreadMap we will convert a list of strings into a map. A SpreadMap is a helper that turns a list with an even number of elements into a Map. In the snippet below, we create a map keyed by NFL city while the value will be the team name.
We can use the map literal syntax [k:v] for creating maps. Basically, it allows us to instantiate a map and define entries in one line. Notice that the keys aren't surrounded by quotes, and by default, Groovy creates an instance of java.
In Groovy, maps created with the literal notation are ordered. We can expect our output to be in the same order as we defined in our original map.
A hashmap maps a key to a value, but you are trying to map a key to two values. To do this, create a hashmap, where the key is your ID and the value is another hashmap, mapping the string "firstname" to "Jack" and the string "lastname" to "Sparrow" and so on for all <person> elements. Morten.
Here's another way to do it, that I think is less obscure while still being fairly concise:
def ml = [a: ["c","d"], b: ["e","f"]]
// Create an empty list that creates empty maps as needed
def lm = [].withDefault{ [:] }
ml.each{ k, values ->
[values].flatten().eachWithIndex { value, index ->
lm[index][k] = value
}
}
assert lm == [[a:"c", b:"e"], [a:"d", b:"f"]]
If you don't want or cannot use withDefault
(because you don't want the list to grow automatically), then this works too:
def ml = [a: ["c","d"], b: ["e","f"]]
def lm = []
ml.each{ k, values ->
[values].flatten().eachWithIndex { value, index ->
lm[index] = lm[index] ?: [:]
lm[index][k] = value
}
}
assert lm == [[a:"c", b:"e"], [a:"d", b:"f"]]
Edit: Added code to handle strings not contained within a list.
Note, the given trick ([values].flatten().eachWithIndex{...}
) is not necessarily very efficient. If speed is essential, then using this would be slightly faster at the expense of readability:
(values instanceof List ? values : [values]).eachWithIndex{...}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With