For_each and count at the same time workaround?

Is there any workaround to use for_each and count?

I am trying to do the following:

locals {
        name_data = {
                "group1" = {
                        name    = "name_"
                        qty = 2
                }
                "group2" = {
                        name    = "name_"
                        qty = 3
                }
                "group3" = {
                        name    = "name_"
                        qty = 1
                }
        }
}

Wanting to accomplish this:

resource "null_resource" "names" {
        for_each = local.name_data
        count = each.value.qty
        triggers = {
                name = each.value.name_[count.index+1]
        }
}

“For Each” of these groups, I want to build the qty of names using “count”. That way the grouped items are all the same, but each group is different.

Hi @william_hashicorp,

count and for_each both apply to the same object, and are not logically nested, therefor you will need to expand the data into the for_each expression itself.

For example, you could use

resource "null_resource" "names" {
  for_each = merge([for k, v in local.name_data :
    { for i in range(v.qty) : "name_${k}_${i + 1}" => k }
  ]...)
}

which will create the instances

  # null_resource.names["name_group1_1"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }

  # null_resource.names["name_group1_2"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }

  # null_resource.names["name_group2_1"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }

  # null_resource.names["name_group2_2"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }

  # null_resource.names["name_group2_3"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }

  # null_resource.names["name_group3_1"] will be created
  + resource "null_resource" "names" {
      + id = (known after apply)
    }
1 Like

Thank you very much!
What you provided does do what you listed, and I didn’t even realize that I’d need that to make the keys distinct.

Now, is there a better way to reference the values of the map? I tried the following, but seems like a lot to get the values,

triggers = {
 name = (lookup(local.name_data, each.value)).name
}

I have tried every syntax of the following:

name = "${"local.name_data.${each.value}.name"}"

Nothing works that way.

Thanks in advance.

Hi @william_hashicorp,

The syntax for looking up an element of a map by a dynamically-chosen key is to use [...] brackets where the brackets contain an expression representing the key to retrieve, like this:

  name = local.name_data[each.value].name
1 Like

@william_hashicorp, I also only didn’t include the map values in the example for_each data because there didn’t appear to be anything else of use there. You can of course construct that mapping however you need so it’s not necessary to lookup the values again in the original map

resource "null_resource" "names" {
  for_each = merge([for k, v in local.name_data :
    { for i in range(v.qty) : "name_${k}_${i + 1}" => v }
  ]...)
}

and then you can access name directly with each.value.name

1 Like

I think what I was doing was to put a dot before the brackets and didn’t try it without:

I was trying:
name = local.name_data.[each.value].name

That was why it never worked for me.

Thank you!

I should have shown more data…was trying to limit the question to only what was necessary.

Tried your change with the value and now I can do each.value.name

I was pretty sure I tried v but it didn’t work before.

Thank you very much!