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