Merging lists into a single list of objects where each list is represented by its own key in each object
How would I merge multiple lists into a single list of objects/dicts, where each list is given its own key name?
e.g.
BobList = [1,2,3,4]
PeterList = ['a','b','c','d']
MergedList = [{'Bob': 1, 'Peter': 'a':}, {'Bob': 2, 'Peter': 'b'} ...] # create this one
I want to be able to name the keys explicitly, they won't match the list name exactly
Solutions
Requirements:
- The number of supplied keys is equal to the number of lists to combine
- The lists being combined are the same length
- The keys should all be unique, otherwise the last lists values associated with that key will be used.
Simple solution by @Transistor
Expression binding
forEach(
asList(1, 2, 3, 4),
asMap(
'Bob', it(),
'Peter', asList('a','b','c','d')[idx()]
)
)
or
forEach(
{this.custom.BobList},
asMap(
'Bob', it(),
'Peter', {this.custom.PeterList}[idx()]
)
)
Note: If length of BobList < length of PeterList the expression will return null.
Advanced solution by @lrose
Use transform()
to snapshot a list of lists (Lists to be combined), then use forEach()
in it's range form to "enumerate" the lists. Finally, use asMap()
and forEach()
to loop over the list of keys, and return a list of lists where each nested list is a key, value pair for the map.
Expression binding
transform(
asList(
asList(1,2,3,4),
asList('a','b','c','d'),
),
forEach(
len(value()[0]), //acts like pythons range()
asMap(
forEach(
asList('Bob','Peter'),
asList(
it(),value()[idx()][idx(1)]
)
)
)
)
)
or
transform(
{path.to.list.of.lists},
forEach(
len(value()[0]),
asMap(
forEach(
{path.to.list.of.keys},
asList(
it(),value()[idx()][idx(1)]
)
)
)
)
)
Advantages
The main advantage of this approach over the one provided by @Transistor is it allows for any arbitrary number of List/Key combinations, with out further editing of the expression. This means that the expression will work even if the expression parameters are produced dynamically, so long as the requirements for the function to work are met.
Using transform()
allows for a single reference to the List of Lists, meaning it can be referenced multiple times throughout the expression with out needing to do the work of dereferencing the property path to get the value. Making the expression more performant, especially as the number of list/key combinations grows.
Some clarification on the inner most forEach()
loop.
In this expression it(), value()[idx()][idx(1)]
, it()
is the current key, value()
is the list of lists, [idx()]
is the current index of the key used to retrieve the list associated with that key from the lists of lists, [idx(1)]
is the value in the associated list at the "enumerated" index.
So the first time through the loop, it would return [['Bob',1],['Peter','a']], which when handed to asMap()
results in the map {'Bob':1,'Peter':'a'}
.
Functions used
- transform() Makes a snapshot of the list of lists.
- forEach() loops through the items in the source.
- asMap() produce a Java Map with string keys.
- asList() unconditionally assembles all of its arguments into a List.
- len() returns the length of its argument.
- it() Delivers the key from the lists of keys
- idx([depth]) retrieves the loop index for an index for the forEach iterator based on the value of its depth argument.