Hi @amsou,
This requirement is a little more specialized than just flattening all values into a single set, and so there isn’t a built-in function to achieve it but you can get this sort of result using for
expressions, which are a more general approach to projecting and filtering data structures.
I think there are a few different ways to get the result you want here, but the one that I find easiest to think about is to split the work into two steps:
- Flatten the data structure into pairs of a single name and a single group, instead of a single name and multiple groups.
- Project those pairs into a map using grouping mode to allow for there being multiple names for the same group.
Here’s one way to achieve step 1:
locals {
dog_group_pairs = toset(flatten([
for d in local.all_dogs.all_dogs : [
for g in d.groups : {
name = d.name
group = g
}
]
]))
}
The result of this expression is a set of objects that each represent a pair of one name and one group, like this:
toset([
{ name = "foo", group = "morning" },
{ name = "foo", group = "evening" },
{ name = "bar", group = "evening" },
{ name = "bar", group = "saturday" },
{ name = "feet", group = "afternoon" },
])
Now we can use this result to achieve step 2, by projecting this set into a map using the group names as the grouping keys:
locals {
group_dogs = tomap({
for pair in local.dog_group_pairs :
pair.group => pair.name...
})
}
The ...
symbol after pair.name
is what activates the grouping mode of the for
expression. Without that, Terraform would raise an error if two elements produced the same key, but with grouping mode enabled Terraform will instead make the map elements all be lists so that multiple input elements with the same key can be grouped together under that key.
The result of this should be the data structure you requested:
tomap({
morning = ["foo"]
evening = ["foo", "bar"]
saturday = ["bar"]
afternoon = ["feet"]
})