Map Block
The map block can be used to create complex maps/objects inside Globals and Lets blocks. It can be used to aggregate lists of objects into maps that have duplicated keys and need a defined way of deep merging values of the same key.
The following is a very basic example introducing the map block inside a globals block:
globals {
map obj {
for_each = [
{ name = "a", value = 5 },
{ name = "c", value = 0 },
{ name = "a", value = 15 },
{ name = "b", value = 5 },
{ name = "c", value = 20 },
]
iterator = elem
key = elem.new.name
value {
value = elem.new.value
previous = tm_try(elem.old.value, null)
}
}
}The code above will result in the global.obj defined below:
obj = {
a = {
previous = 5
value = 15
}
b = {
previous = null
value = 5
}
c = {
previous = 0
value = 20
}
}The map will iterate over the values in for_each, setting the iterator variable (elem in this case, element by default) with the elem.new and elem.old values for the provided key. The elem.new contains the current iterated value and the elem.old contains the values of the previous iteration of the current key.
Now it's time for a more useful example.
Take a look at the global.orders list declared below:
globals {
orders = [
{ name = "Morpheus", product = "sunglass", price = 100.5 },
{ name = "Trinity", product = "cape", price = 82.30 },
{ name = "Trinity", product = "necklace", price = 25.0 },
{ name = "Trinity", product = "sunglass", price = 100.5 },
{ name = "Anderson", product = "ollydbg", price = 30 },
{ name = "Morpheus", product = "boot", price = 65 },
{ name = "Anderson", product = "cape", price = 82.30 },
{ name = "Morpheus", product = "sunglass", price = 145.50 },
]
}Let's aggregate those values by name, by using the map block as defined below:
globals {
map totals {
for_each = global.orders
key = element.new.name
value {
total_spent = tm_try(element.old.total_spent, 0) + element.new.price
}
}
}Which will result in the global object below:
totals = {
Anderson = {
total_spent = 112.3
}
Morpheus = {
total_spent = 311
}
Trinity = {
total_spent = 207.8
}
}Using nested map blocks and then aggregating by product for each name can be achieved using the following:
Example:
globals {
map totals {
for_each = global.orders
iterator = per_name
key = per_name.new.name
value {
total_spent = tm_try(per_name.old.total_spent, 0) + per_name.new.price
map per_product {
for_each = [for v in global.orders : v if v.name == per_name.new.name]
iterator = per_product
key = per_product.new.product
value {
total = tm_try(per_product.old.total, 0) + per_product.new.price
}
}
}
}
}which will result the object below:
obj = {
Anderson = {
total_spent = 112.3
per_product = {
cape = {
total = 82.3
}
ollydbg = {
total = 30
}
}
}
Morpheus = {
total_spent = 311
per_product = {
boot = {
total = 65
}
sunglass = {
total = 246
}
}
}
Trinity = {
total_spent = 207.8
per_product = {
cape = {
total = 82.3
}
necklace = {
total = 25
}
sunglass = {
total = 100.5
}
}
}
}