You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并Terraform Map中的对象列表,聚合指定键的值?

Terraform 合并对象列表:保留标量键,合并值为集合/列表/字符串

我需要合并local.what_i_have_v2中的对象列表,将instance_id、tag_name这类值完全相同的键保留为标量,将tag_value这类键的值合并为集合、列表或拼接成字符串。

现有数据

locals {
  what_i_have_v2 = {
    "cluster=foo|instance=foo#1|tag=tag1" = [
      {
        instance_id = "i-fff11111"
        tag_name = "tag1"
        tag_value = "val1_a"
      },
      {
        instance_id = "i-fff11111"
        tag_name = "tag1"
        tag_value = "val1_b"
      },
    ],
    "cluster=foo|instance=foo#2|tag=tag1" = [
      {
        instance_id = "i-fff22222"
        tag_name = "tag1"
        tag_value = "val1_a"
      },
      {
        instance_id = "i-fff22222"
        tag_name = "tag1"
        tag_value = "val1_b"
      },
    ],
    "cluster=bar|instance=bar#1|tag=tag1" = [
      {
        instance_id = "i-bbb11111"
        tag_name = "tag1"
        tag_value = "val1_a"
      },
    ],
    "cluster=bar|instance=bar#1|tag=tag2" = [
      {
        instance_id = "i-bbb11111"
        tag_name = "tag2"
        tag_value = "val2_a"
      },
      {
        instance_id = "i-bbb11111"
        tag_name = "tag2"
        tag_value = "val2_b"
      },
    ],
  },
}

期望输出

格式1:映射结构(保留实例级键)

locals {
  what_i_want_v1 = {
    "cluster=foo|instance=foo#1" = {
      instance_id = "i-fff11111"
      tag_name = "tag1"
      tag_value = ["val1_a", "val1_b"] # 相同键下的值合并为列表
    },
    "cluster=foo|instance=foo#2" = {
      instance_id = "i-fff22222"
      tag_name = "tag1"
      tag_value = ["val1_a", "val1_b"]
    },
    "cluster=bar|instance=bar#1" = {
      instance_id = "i-bbb11111"
      tag_name = "tag1"
      tag_value = ["val1_a"]
    },
    "cluster=bar|instance=bar#1" = {
      instance_id = "i-bbb11111"
      tag_name = "tag2"
      tag_value = ["val2_a", "val2_b"]
    },
  },
}

格式2:列表结构

locals {
  what_i_want_v2 = [
    {
      instance_id = "i-fff11111"
      tag_name = "tag1"
      tag_value = ["val1_a", "val1_b"]
    },
    {
      instance_id = "i-fff22222"
      tag_name = "tag1"
      tag_value = ["val1_a", "val1_b"]
    },
    {
      instance_id = "i-bbb11111"
      tag_name = "tag1"
      tag_value = ["val1_a"]
    },
    {
      instance_id = "i-bbb11111"
      tag_name = "tag2"
      tag_value = ["val2_a", "val2_b"]
    },
  ],
}

格式3:列表结构(值拼接为字符串)

locals {
  what_i_want_v3 = [
    {
      instance_id = "i-fff11111"
      tag_name = "tag1"
      tag_value = "val1_a+val1_b" # 值用"+"拼接为字符串
    },
    {
      instance_id = "i-fff22222"
      tag_name = "tag1"
      tag_value = "val1_a+val1_b"
    },
    {
      instance_id = "i-bbb11111"
      tag_name = "tag1"
      tag_value = "val1_a"
    },
    {
      instance_id = "i-bbb11111"
      tag_name = "tag2"
      tag_value = "val2_a+val2_b"
    },
  ],
}

尝试过的方法(无效)

使用merge()函数会直接覆盖重复键的值,无法实现合并:

locals {
 attempt_1 = {for k, v in local.what_i_have: k => merge(v...)}
}

结果:

# attempt_1 =
{
  "cluster=bar|instance=bar#1" = {
    instance_id = "i-bbb11111"
    tag_name    = "tag1"
    tag_value   = "val1_a"
  }
  "cluster=foo|instance=foo#1" = {
    instance_id = "i-fff11111"
    tag_name    = "tag1"
    tag_value   = "val1_b"
  }
  "cluster=foo|instance=foo#2" = {
    instance_id = "i-fff22222"
    tag_name    = "tag1"
    tag_value   = "val1_b"
  }
}

可行解决方案

实现what_i_want_v1(映射结构)

利用正则表达式提取实例级键,结合for表达式收集tag_value:

locals {
  what_i_want_v1 = {
    for k, objs in local.what_i_have_v2 :
    // 从原始键中移除|tag=xxx部分,得到实例级标识
    regex_replace(k, "\\|tag=.+$", "") => {
      instance_id = objs[0].instance_id // 列表内instance_id一致,取第一个即可
      tag_name    = objs[0].tag_name    // 列表内tag_name一致,取第一个即可
      tag_value   = [for o in objs : o.tag_value] // 收集所有tag_value到列表
    }
  }
}

实现what_i_want_v2(列表结构)

直接提取what_i_want_v1的所有值转成列表:

locals {
  what_i_want_v2 = values(local.what_i_want_v1)
}

实现what_i_want_v3(值拼接为字符串)

基于what_i_want_v2,用join()函数将列表值拼接为字符串:

locals {
  what_i_want_v3 = [
    for item in local.what_i_want_v2 :
    merge(item, { tag_value = join("+", item.tag_value) })
  ]
}

补充说明

由于what_i_have_v2中每个键对应的对象列表里,instance_id和tag_name的值完全一致,因此可以安全地取列表第一个元素的对应值作为标量。如果后续存在值不一致的情况,可以先通过distinct()函数验证,避免出现数据不一致问题。

内容的提问来源于stack exchange,提问作者CDuv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:08:09