github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/website/content/docs/job-specification/hcl2/functions/collection/flatten.mdx (about) 1 --- 2 layout: docs 3 page_title: flatten - Functions - Configuration Language 4 description: The flatten function eliminates nested lists from a list. 5 --- 6 7 # `flatten` Function 8 9 `flatten` takes a list and replaces any elements that are lists with a 10 flattened sequence of the list contents. 11 12 ## Examples 13 14 ```shell-session 15 > flatten([["a", "b"], [], ["c"]]) 16 ["a", "b", "c"] 17 ``` 18 19 If any of the nested lists also contain directly-nested lists, these too are 20 flattened recursively: 21 22 ```shell-session 23 > flatten([[["a", "b"], []], ["c"]]) 24 ["a", "b", "c"] 25 ``` 26 27 Indirectly-nested lists, such as those in maps, are _not_ flattened. 28 29 <!--- 30 31 ## TODO: revamp this section 32 33 ## Flattening nested structures for `for_each` 34 35 The 36 [resource `for_each`](https://www.terraform.io/docs/configuration/resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings) 37 and 38 [`dynamic` block](/docs/job-specification/hcl2/expressions#dynamic-blocks) 39 language features both require a collection value that has one element for 40 each repetition. 41 42 Sometimes your input data structure isn't naturally in a suitable shape for 43 use in a `for_each` argument, and `flatten` can be a useful helper function 44 when reducing a nested data structure into a flat one. 45 46 For example, consider a folder that declares a variable like the following: 47 48 ```hcl 49 variable "networks" { 50 type = map(object({ 51 cidr_block = string 52 subnets = map(object({ 53 cidr_block = string 54 }) 55 }) 56 } 57 ``` 58 59 The above is a reasonable way to model objects that naturally form a tree, 60 such as top-level networks and their subnets. The repetition for the top-level 61 networks can use this variable directly, because it's already in a form 62 where the resulting instances match one-to-one with map elements: 63 64 ```hcl 65 resource "aws_vpc" "example" { 66 for_each = var.networks 67 68 cidr_block = each.value.cidr_block 69 } 70 ``` 71 72 However, in order to declare all of the _subnets_ with a single `resource` 73 block, we must first flatten the structure to produce a collection where each 74 top-level element represents a single subnet: 75 76 ```hcl 77 locals { 78 # flatten ensures that this local value is a flat list of objects, rather 79 # than a list of lists of objects. 80 network_subnets = flatten([ 81 for network_key, network in var.networks : [ 82 for subnet_key, subnet in network.subnets : { 83 network_key = network_key 84 subnet_key = subnet_key 85 network_id = aws_vpc.example[network_key].id 86 cidr_block = subnet.cidr_block 87 } 88 ] 89 ]) 90 } 91 92 resource "aws_subnet" "example" { 93 # local.network_subnets is a list, so we must now project it into a map 94 # where each key is unique. We'll combine the network and subnet keys to 95 # produce a single unique key per instance. 96 for_each = { 97 for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet 98 } 99 100 vpc_id = each.value.network_id 101 availability_zone = each.value.subnet_key 102 cidr_block = each.value_cidr_block 103 } 104 ``` 105 106 The above results in one subnet instance per subnet object, while retaining 107 the associations between the subnets and their containing networks. 108 109 --> 110 111 ## Related Functions 112 113 - [`setproduct`](/docs/job-specification/hcl2/functions/collection/setproduct) finds all of the combinations of multiple 114 lists or sets of values, which can also be useful when preparing collections 115 for use with `for_each` constructs.