用于散列转换的哈希数组,同时防止键覆盖

时间:2013-05-31 21:58:48

标签: ruby arrays hash

你会如何转换:

x = [
 {"a" => ["a","b","c","d","e"]}, 
 {"f" => ["f","g","h","i","j","k","l","m","n"]}, 
 {"f" => ["o","p"]}
]

进入:

{
 "a"=>["a", "b", "c", "d", "e"], 
 "f" => ["f","g","h","i","j","k","l","m","n"]}, 
 "f01"=>["o", "p"] 
}

我最初使用的是

x.reduce({},:update)

但是这会覆盖第一个“f”(因为键是唯一的)。

我已经仔细寻找答案,但在这种情况下找不到任何可行的方法。

4 个答案:

答案 0 :(得分:4)

更改密钥后产生的哈希将导致一个非常困难的问题:如何轻松查找生成的哈希及其数组?

我建议重新考虑你想要的哈希类型。不是创建难以查找并且与原始散列密钥具有脆弱关联的新散列密钥,而是重用原始密钥并创建指向数组阵列的散列密钥。从一个更简单的起始哈希数组开始:

x = [
  {'a' => ['a', 'b']},
  {'f' => ['f', 'g']},
  {'f' => ['o', 'p']}
]

以下是代码:

hash = x.each_with_object(Hash.new{ |h, k| h[k] = [] }) { |e, h| 
  k, v = e.flatten
  h[k] << v
}

pp hash

这是输出:

{"a"=>[["a", "b"]], "f"=>[["f", "g"], ["o", "p"]]}

查找变得更加简单:

hash['f'][0]
# => ["f", "g"]
hash['f'].last
# => ["o", "p"]

您可以保持原始数组的分离,同时获得更合理且更简单的查找。

如果您需要知道为哈希分配了多少个子阵列,也很容易:

hash['f'].size
# => 2

如果您想迭代所有'f'条目,这会使您的设计变得困惑和困难,只需执行以下操作:

hash['f'].each do |f|
  ...
end

或:

hash['f'].map { |f|
  ...
}

答案 1 :(得分:1)

假设01的{​​{1}}部分只是一个计数器,而您不关心格式化该数字,则可以执行以下操作:

f01

呸。

答案 2 :(得分:1)

您可以使用inject,如下所示:

 > x.inject({}){|r,h| r[h.keys.first] ||= [] ; r[h.keys.first] << h.values.first; r}
  => {"a"=>[["a", "b", "c", "d", "e"]], 
      "f"=>[["f", "g", "h", "i", "j", "k", "l", "m", "n"], ["o", "p"]]} 

请注意,您将获得同一密钥的多个阵列。 (I.E. "f"

生成的哈希值与您要求的略有不同,但它可能更容易使用,因为修改后的密钥没有混淆。

答案 3 :(得分:1)

x = [
 {"a" => ["a","b","c","d","e"]}, 
 {"f" => ["f","g","h","i","j","k","l","m","n"]}, 
 {"f" => ["o","p"]}
]

res = x.collect{|d| d.first}.each_with_object({}) do |(k,v), h, n = "00"|
  (k += n.next!) if (h.key? k)
  h[k] = v
end

res == {
 "a"=>["a", "b", "c", "d", "e"], 
 "f" => ["f","g","h","i","j","k","l","m","n"], 
 "f01"=>["o", "p"] 
}