Puppet:将数组深度合并到哈希中

Puppet: Deep merge of an array into a Hash

我在 puppet 中有一个嵌套数组

$rules = [ [service1, rule1], [service1, rule2], [service2, rule3], [service3, rule4] ]

我需要将其转换为以下散列

$rules_hash = {
  'service1' => ['rule1', 'rule2'],
  'service2' => ['rule3'],
  'service3' => ['rule4'],
}

我尝试使用内置的 Hash() 函数,但它不是一个选项,因为当有重复的键时,它 returns 只是该键的最后一个实例,给我留下一个不完整的散列每个键只有一个值。

我也尝试过使用 reduce() 来迭代数组并为具有公共键的值创建一个字符串 "rule1 rule2",但是使用 reduce() 嵌套数组会变平并且它如果不明确声明数组的哪个元素应该是键,就无法区分我要创建的哈希的键和值(如果数组有很多不同的键,这将变得不可行)。

有多种方法可以做到这一点,但这个非常干净。它首先使用 built-in group_by 函数来完成繁重的工作:这从一个数组到一个散列,其中键是你想要的,但值是原始数组的数组.例如,给定 ...

$rules = [ [service1, rule1], [service1, rule2], [service2, rule3], [service3, rule4] ]

...这个...

$rules.group_by |$rule| { $rule[0] }

...按每个成员数组的第一个元素分组以产生此散列:

{
  service1 => [[service1, rule1], [service1, rule2]],
  service2 => [[service2, rule3]],
  service3 => [[service3, rule4]]
}

。你会认识到那与你所追求的有关,但并不完全如此。然而,结果散列中的值非常适合通过应用 map() 函数转换为想要的值:

[[service1, rule1], [service1, rule2]].map |$sr| { $sr[1] }
# yields [ rule1, rule2 ]

可以通过使用 reduce() function in conjunction with Puppet's built in hash-merging operator (+) 在 per-element 的基础上应用于中间散列。总的来说,这可能看起来像这样:

$rules = [ [service1, rule1], [service1, rule2], [service2, rule3], [service3, rule4] ]

$rules_hash = $rules.group_by |$rule| { $rule[0] } .reduce({}) |$memo, $entry| {
  $memo + { $entry[0] => $entry[1].map |$rule| { $rule[1] } }
}