跳至主要内容

flatten 函数

flatten 接收一个列表,并将列表中任何元素(如果为列表)替换为列表内容的扁平化序列。

示例

代码块
> flatten([["a", "b"], [], ["c"]])
["a", "b", "c"]

如果任何嵌套列表也包含直接嵌套的列表,这些列表也会递归地扁平化。

代码块
> flatten([[["a", "b"], []], ["c"]])
["a", "b", "c"]

间接嵌套的列表(例如地图中的列表)不会被扁平化。

for_each 扁平化嵌套结构

资源 for_eachdynamic 语言功能都要求一个集合值,该值对每次重复都有一个元素。

有时你的输入数据结构不能自然地以适合在 for_each 参数中使用的形状出现,而 flatten 在将嵌套数据结构简化为扁平结构时可能是一个有用的辅助函数。

例如,考虑一个声明以下变量的模块

代码块
variable "networks" {
type = map(object({
cidr_block = string
subnets = map(object({ cidr_block = string }))
}))
}

以上是为自然形成树状结构的对象(如顶级网络及其子网)建模的一种合理方式。顶级网络的重复可以直接使用此变量,因为它已经是这样一种形式:结果实例与地图元素一一对应。

代码块
resource "aws_vpc" "example" {
for_each = var.networks

cidr_block = each.value.cidr_block
}

但是,为了用单个 resource 块声明所有子网,我们必须首先扁平化结构,以生成一个集合,其中每个顶级元素都代表一个子网。

代码块
locals {
# flatten ensures that this local value is a flat list of objects, rather
# than a list of lists of objects.
network_subnets = flatten([
for network_key, network in var.networks : [
for subnet_key, subnet in network.subnets : {
network_key = network_key
subnet_key = subnet_key
network_id = aws_vpc.example[network_key].id
cidr_block = subnet.cidr_block
}
]
])
}

resource "aws_subnet" "example" {
# local.network_subnets is a list, so we must now project it into a map
# where each key is unique. We'll combine the network and subnet keys to
# produce a single unique key per instance.
for_each = {
for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
}

vpc_id = each.value.network_id
availability_zone = each.value.subnet_key
cidr_block = each.value.cidr_block
}

以上结果是每个子网对象一个子网实例,同时保留子网与其包含的网络之间的关联。

  • setproduct 查找多个列表或值集的所有组合,这在为使用 for_each 结构准备集合时也很有用。