通过列表项之一加入列表列表
Join list of lists by one of the list items
我有这个列表结构列表:
[
["nginx-66b6c48dd5-25wv5", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-2nhbs", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-5b4dw", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-p7sx9", "nginx-deployment", "worker-1", "0", "2"],
["coredns-autoscaler-76f8869cc9-gd69j", "kube-system", "worker-1", "1", "5"],
["coredns-55b58f978-q2skn", "kube-system", "worker-1", "7", "11"]
]
我想通过第二个列表项(nginx-deployment、kube-system 等)合并它们,然后将两个最新的项目相加并删除第一个项目。
所以它看起来像这样:
[
["nginx-deployment", "worker-1", "0", "8"],
["kube-system", "worker-1", "8", "16"]
]
Enum.zip 有点管用,但我必须先拆分子列表,我认为必须有更好的方法来做到这一点。
对于这个,我会使用 Enum.reduce
,在此过程中将列表转换为地图。
想法是“循环”列表,每次用总和更新“累加器”映射,如下所示:
[
["nginx-66b6c48dd5-25wv5", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-2nhbs", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-5b4dw", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-p7sx9", "nginx-deployment", "worker-1", "0", "2"],
["coredns-autoscaler-76f8869cc9-gd69j", "kube-system", "worker-1", "1", "5"],
["coredns-55b58f978-q2skn", "kube-system", "worker-1", "7", "11"]
]
|> Enum.reduce(%{}, fn [_, key, _, stat0, stat1], accumulator ->
int0 = String.to_integer(stat0)
int1 = String.to_integer(stat1)
Map.update(accumulator, key, {int0, int1}, fn {x, y} -> {x + int0, y + int1} end)
end)
那会 return:
%{"kube-system" => {8, 16}, "nginx-deployment" => {0, 8}}
注意:我没有包括“第三”字段,因为我不确定应该如何选择它。它总是独一无二的吗?无论如何,我的回答概述了我将如何处理这个问题。
如果第三个字段可能不是唯一的,@PeacefulJames 的解决方案(在其他方面绝对正确)可能由于硬编码的内容而过于脆弱。这是更冗长但更好的可扩展解决方案,涉及 Enum.group_by/3
.
list
|> Enum.group_by(
&Enum.slice(&1, 1..2),
fn e ->
e
|> Enum.take(-2)
|> Enum.map(&String.to_integer/1)
end
) |> Enum.map(fn {k, v} ->
k ++ Enum.reduce(v, [0, 0], fn [x, y], [xx, yy] -> [x + xx, y + yy] end)
end)
#⇒ [["kube-system", "worker-1", 8, 16],
# ["nginx-deployment", "worker-1", 0, 8]]
我有这个列表结构列表:
[
["nginx-66b6c48dd5-25wv5", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-2nhbs", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-5b4dw", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-p7sx9", "nginx-deployment", "worker-1", "0", "2"],
["coredns-autoscaler-76f8869cc9-gd69j", "kube-system", "worker-1", "1", "5"],
["coredns-55b58f978-q2skn", "kube-system", "worker-1", "7", "11"]
]
我想通过第二个列表项(nginx-deployment、kube-system 等)合并它们,然后将两个最新的项目相加并删除第一个项目。
所以它看起来像这样:
[
["nginx-deployment", "worker-1", "0", "8"],
["kube-system", "worker-1", "8", "16"]
]
Enum.zip 有点管用,但我必须先拆分子列表,我认为必须有更好的方法来做到这一点。
对于这个,我会使用 Enum.reduce
,在此过程中将列表转换为地图。
想法是“循环”列表,每次用总和更新“累加器”映射,如下所示:
[
["nginx-66b6c48dd5-25wv5", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-2nhbs", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-5b4dw", "nginx-deployment", "worker-1", "0", "2"],
["nginx-66b6c48dd5-p7sx9", "nginx-deployment", "worker-1", "0", "2"],
["coredns-autoscaler-76f8869cc9-gd69j", "kube-system", "worker-1", "1", "5"],
["coredns-55b58f978-q2skn", "kube-system", "worker-1", "7", "11"]
]
|> Enum.reduce(%{}, fn [_, key, _, stat0, stat1], accumulator ->
int0 = String.to_integer(stat0)
int1 = String.to_integer(stat1)
Map.update(accumulator, key, {int0, int1}, fn {x, y} -> {x + int0, y + int1} end)
end)
那会 return:
%{"kube-system" => {8, 16}, "nginx-deployment" => {0, 8}}
注意:我没有包括“第三”字段,因为我不确定应该如何选择它。它总是独一无二的吗?无论如何,我的回答概述了我将如何处理这个问题。
如果第三个字段可能不是唯一的,@PeacefulJames 的解决方案(在其他方面绝对正确)可能由于硬编码的内容而过于脆弱。这是更冗长但更好的可扩展解决方案,涉及 Enum.group_by/3
.
list
|> Enum.group_by(
&Enum.slice(&1, 1..2),
fn e ->
e
|> Enum.take(-2)
|> Enum.map(&String.to_integer/1)
end
) |> Enum.map(fn {k, v} ->
k ++ Enum.reduce(v, [0, 0], fn [x, y], [xx, yy] -> [x + xx, y + yy] end)
end)
#⇒ [["kube-system", "worker-1", 8, 16],
# ["nginx-deployment", "worker-1", 0, 8]]