# For\_each objects to list

**URL:** <https://discuss.hashicorp.com/t/for-each-objects-to-list/36609>\
**Category:** Terraform\
**Created:** [March 5, 2022, 4:00pm UTC](https://discuss.hashicorp.com/t/for-each-objects-to-list/36609 "2022-03-05T16:00:52Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jenny-law](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/jenny-law/32/26461_2.png) [@jenny-law](https://discuss.hashicorp.com/u/jenny-law)\
**Post date:** [March 5, 2022, 4:00pm UTC](https://discuss.hashicorp.com/t/for-each-objects-to-list/36609/1 "2022-03-05T16:00:52Z")

</div>

I need to get the results of the following objects from the for\_each loop into an array to use as an attribute within another resource.

```auto
client_vpce_ids= [
    {
        account_id= "123456789101",
        vpc_id= "vpce-xxxxxxxxxxxxxxx"
    },
    {
        account_id= "123456789102",
        vpc_id= "vpce-yyyyyyyyyyyyyyy"
    }
]

resource "first_resource" "first_example" {

  for_each = { for vpce in var.CLIENT_VPCE_IDS : vpce.account_id => vpce }

  name = "${each.value.account_id}-access-vpce"

 rule {

    source = "${each.value.vpc_id}"

  }

}

```

I then need to add all the first\_resource.first\_example object ids to an array to use in another resource e.g.

```auto
resource "second_resource" "second_example" {

    array = [first_resource.first_example[key1].id,
                  first_resource.first_example[key2].id
                   ]
}

```

But I’m struggling to know either how to work out what key1,key2,key3 etc… should be and how to dynamically add\remove them. I’ve tried with locals e.g.

```auto
locals {

    for_each = first_resource.first_example
    array = each.value.id

}

```

But this isn’t supported.

Any help very much appreciated.

---

<div class="post-metadata">

**Author:** ![apparentlymart](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/apparentlymart/32/702_2.png) [@apparentlymart](https://discuss.hashicorp.com/u/apparentlymart)\
**Post date:** [March 7, 2022, 4:46pm UTC](https://discuss.hashicorp.com/t/for-each-objects-to-list/36609/2 "2022-03-07T16:46:03Z")

</div>

Hi @jenny-law,

The `for_each` argument is for declaring multiple instances of a resource or module using a single `resource`, `data`, or `module` block.

However, the situation you’re describing here is manipulating a data structure rather than declaring resources/modules, and any time we’re manipulating values we use [expressions](https://www.terraform.io/language/expressions).

For projecting one data structure in another the most relevant kind of expression is [`for` expressions](https://www.terraform.io/language/expressions/for), which take one collection as input and produce another collection as the result.

So with all of that said, the problem you’ve presented here is taking a map of objects as produced by a resource with a `for_each` block, and projecting that into a list of values taken from the `id` attributes of those objects. You can write that as follows:

```auto
  array = [
    for o in first_resource.first_example : o.id
  ]

```

I called this argument “array” to match what you shared but please note that there’s no such data type as “array” in Terraform. Instead, this argument probably requires either a _list_ or a _set_. The difference between these is that a list preserves the order of the objects and allows duplicates, whereas a set is just like a bag of values that are in no particular order and have no duplicates.

Most of the time you don’t need to worry too much about this distinction, but I mention it here because map elements are not ordered either and so projecting a map into a list as shown above requires Terraform to choose an ordering for the map. Terraform will visit the map elements in lexical order by map key, so if this resource argument is expecting a list then the ordering of the IDs will be the same as the sorted order of the map keys. If the second resource type actually expects a set then this won’t matter, because Terraform will automatically convert the list into a set and thus discard the ordering.

---

<div class="post-metadata">

**Author:** ![jenny-law](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/jenny-law/32/26461_2.png) [@jenny-law](https://discuss.hashicorp.com/u/jenny-law)\
**Post date:** [March 17, 2022, 11:53am UTC](https://discuss.hashicorp.com/t/for-each-objects-to-list/36609/3 "2022-03-17T11:53:53Z")

</div>

Thank you that’s really helpful. I’m having other issues. If I wanted to take a list of maps,

e.g.

```auto
variable "TAGS"=[
{"Key":"billing_team","Value":"santa"},
"Key":"cost_centre","Value":"200142"}
]

and make
tags={"billing_team"="santa", "cost_centre"="200142" }

I'm trying various version of 
locals {
  tags = [  

  for key, value in var.TAGS: map({value[0] = value[1]})

 ]
}

```

but I’m missing something with the logic still…

---

<div class="post-metadata">

**Author:** ![jenny-law](https://sea2.discourse-cdn.com/hashicorp/user_avatar/discuss.hashicorp.com/jenny-law/32/26461_2.png) [@jenny-law](https://discuss.hashicorp.com/u/jenny-law)\
**Post date:** [March 18, 2022, 8:24am UTC](https://discuss.hashicorp.com/t/for-each-objects-to-list/36609/4 "2022-03-18T08:24:08Z")

</div>

Finally got there  
locals {

keys = [

for map in var.TAGS: [

```
for key, value in map: value ]

```

]

tags = [

```
for str in local.keys:

{

tag = tomap({"${str[0]}" = "${str[1]}"})

}

```

]

mandatory\_tags = merge(local.tags[\*].tag…)

}

Not sure if this is the best\ most elegant method but… it works
