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