github.com/pulumi/terraform@v1.4.0/website/docs/language/expressions/for.mdx (about) 1 --- 2 page_title: For Expressions - Configuration Language 3 description: >- 4 For expressions transform complex input values into complex output values. 5 Learn how to filter inputs and how to group results. 6 --- 7 8 # `for` Expressions 9 10 A _`for` expression_ creates a complex type value by transforming 11 another complex type value. Each element in the input value 12 can correspond to either one or zero values in the result, and an arbitrary 13 expression can be used to transform each input element into an output element. 14 15 For example, if `var.list` were a list of strings, then the following expression 16 would produce a tuple of strings with all-uppercase letters: 17 18 ```hcl 19 [for s in var.list : upper(s)] 20 ``` 21 22 This `for` expression iterates over each element of `var.list`, and then 23 evaluates the expression `upper(s)` with `s` set to each respective element. 24 It then builds a new tuple value with all of the results of executing that 25 expression in the same order. 26 27 ## Input Types 28 29 A `for` expression's input (given after the `in` keyword) can be a list, 30 a set, a tuple, a map, or an object. 31 32 The above example showed a `for` expression with only a single temporary 33 symbol `s`, but a `for` expression can optionally declare a pair of temporary 34 symbols in order to use the key or index of each item too: 35 36 ```hcl 37 [for k, v in var.map : length(k) + length(v)] 38 ``` 39 40 For a map or object type, like above, the `k` symbol refers to the key or 41 attribute name of the current element. You can also use the two-symbol form 42 with lists and tuples, in which case the additional symbol is the index 43 of each element starting from zero, which conventionally has the symbol name 44 `i` or `idx` unless it's helpful to choose a more specific name: 45 46 ```hcl 47 [for i, v in var.list : "${i} is ${v}"] 48 ``` 49 50 The index or key symbol is always optional. If you specify only a single 51 symbol after the `for` keyword then that symbol will always represent the 52 _value_ of each element of the input collection. 53 54 ## Result Types 55 56 The type of brackets around the `for` expression decide what type of result 57 it produces. 58 59 The above example uses `[` and `]`, which produces a tuple. If you use `{` and 60 `}` instead, the result is an object and you must provide two result 61 expressions that are separated by the `=>` symbol: 62 63 ```hcl 64 {for s in var.list : s => upper(s)} 65 ``` 66 67 This expression produces an object whose attributes are the original elements 68 from `var.list` and their corresponding values are the uppercase versions. 69 For example, the resulting value might be as follows: 70 71 ```hcl 72 { 73 foo = "FOO" 74 bar = "BAR" 75 baz = "BAZ" 76 } 77 ``` 78 79 A `for` expression alone can only produce either an object value or a tuple 80 value, but Terraform's automatic type conversion rules mean that you can 81 typically use the results in locations where lists, maps, and sets are expected. 82 83 ## Filtering Elements 84 85 A `for` expression can also include an optional `if` clause to filter elements 86 from the source collection, producing a value with fewer elements than 87 the source value: 88 89 ``` 90 [for s in var.list : upper(s) if s != ""] 91 ``` 92 93 One common reason for filtering collections in `for` expressions is to split 94 a single source collection into two separate collections based on some 95 criteria. For example, if the input `var.users` is a map of objects where the 96 objects each have an attribute `is_admin` then you may wish to produce separate 97 maps with admin vs non-admin objects: 98 99 ```hcl 100 variable "users" { 101 type = map(object({ 102 is_admin = bool 103 })) 104 } 105 106 locals { 107 admin_users = { 108 for name, user in var.users : name => user 109 if user.is_admin 110 } 111 regular_users = { 112 for name, user in var.users : name => user 113 if !user.is_admin 114 } 115 } 116 ``` 117 118 ## Element Ordering 119 120 Because `for` expressions can convert from unordered types (maps, objects, sets) 121 to ordered types (lists, tuples), Terraform must choose an implied ordering 122 for the elements of an unordered collection. 123 124 For maps and objects, Terraform sorts the elements by key or attribute name, 125 using lexical sorting. 126 127 For sets of strings, Terraform sorts the elements by their value, using 128 lexical sorting. 129 130 For sets of other types, Terraform uses an arbitrary ordering that may change in future versions. We recommend converting the expression result into a set to make it clear elsewhere in the configuration that the result is unordered. You can use [the `toset` function](/language/functions/toset) 131 to concisely convert a `for` expression result to be of a set type. 132 133 ```hcl 134 toset([for e in var.set : e.example]) 135 ``` 136 137 ## Grouping Results 138 139 If the result type is an object (using `{` and `}` delimiters) then normally 140 the given key expression must be unique across all elements in the result, 141 or Terraform will return an error. 142 143 Sometimes the resulting keys are _not_ unique, and so to support that situation 144 Terraform supports a special _grouping mode_ which changes the result to support 145 multiple elements per key. 146 147 To activate grouping mode, add the symbol `...` after the value expression. 148 For example: 149 150 ```hcl 151 variable "users" { 152 type = map(object({ 153 role = string 154 })) 155 } 156 157 locals { 158 users_by_role = { 159 for name, user in var.users : user.role => name... 160 } 161 } 162 ``` 163 164 The above represents a situation where a module expects a map describing 165 various users who each have a single "role", where the map keys are usernames. 166 The usernames are guaranteed unique because they are map keys in the input, 167 but many users may all share a single role name. 168 169 The `local.users_by_role` expression inverts the input map so that the keys 170 are the role names and the values are usernames, but the expression is in 171 grouping mode (due to the `...` after `name`) and so the result will be a 172 map of lists of strings, such as the following: 173 174 ```hcl 175 { 176 "admin": [ 177 "ps", 178 ], 179 "maintainer": [ 180 "am", 181 "jb", 182 "kl", 183 "ma", 184 ], 185 "viewer": [ 186 "st", 187 "zq", 188 ], 189 } 190 ``` 191 192 Due to [the element ordering rules](#element-ordering), Terraform will sort 193 the users lexically by username as part of evaluating the `for` expression, 194 and so the usernames associated with each role will be lexically sorted 195 after grouping. 196 197 ## Repeated Configuration Blocks 198 199 The `for` expressions mechanism is for constructing collection values from 200 other collection values within expressions, which you can then assign to 201 individual resource arguments that expect complex values. 202 203 Some resource types also define _nested block types_, which typically represent 204 separate objects that belong to the containing resource in some way. You can't 205 dynamically generate nested blocks using `for` expressions, but you _can_ 206 generate nested blocks for a resource dynamically using 207 [`dynamic` blocks](/language/expressions/dynamic-blocks).