【问题标题】:Convert hash to array of hashes将哈希转换为哈希数组
【发布时间】:2019-05-23 03:49:05
【问题描述】:

我有哈希,它的所有值都是数组,像这样:

list = { letter:  ['a', 'b', 'c'],
         number:  ['one', 'two', 'three'],
         fruit:   ['apple', 'pear', 'kiwi'],
         car:     ['vw', 'mb', 'bmw'],
         state:   ['la', 'ny', 'fl'],
         color:   ['red', 'white', 'black'],
         tree:    ['oak', 'pine', 'maple'],
         animal:  ['cat', 'dog', 'rat'],
         clothes: ['tie', 'sock', 'glove'] }

事实上,这个散列可以有更多的键和值可以更大,但每个值的大小总是相同的(在这种情况下 - 三个)。

我想将此哈希转换为哈希数组。

每个散列将具有原始散列的所有键和相应的值。

所以最后我想拥有:

list = [
  { letter: 'a', number: 'one', fruit: 'apple', car: 'vw', state: 'la',
    color: 'red', tree: 'oak', animal: 'cat', clothes: 'tie' },

  { letter: 'b', number: 'two', fruit: 'pear', car: 'mb', state: 'ny',
    color: 'white', tree: 'pine', animal: 'dog', clothes: 'sock' },

  { letter: 'c', number: 'three', fruit: 'kiwi', car: 'bmw', state: 'fl',
    color: 'black', tree: 'elm', animal: 'rat', clothes: 'glove' }
]

最好的方法是什么?

【问题讨论】:

    标签: arrays ruby hashmap


    【解决方案1】:

    试试下面的代码,

    arr = []
    3.times { |x| arr[x] = {}; list.each { |k,v| arr[x][k] = v[x] } }
    arr.inspect
    

    输出将是

    => [{:letter=>"a", :number=>"one", :fruit=>"apple", :car=>"vw", :state=>"la", :color=>"red", :tree=>"oak", :animal=>"cat", :clothes=>"tie"}, {:letter=>"b", :number=>"two", :fruit=>"pear", :car=>"mb", :state=>"ny", :color=>"white", :tree=>"pine", :animal=>"dog", :clothes=>"sock"}, {:letter=>"c", :number=>"three", :fruit=>"kiwi", :car=>"bmw", :state=>"fl", :color=>"black", :tree=>"maple", :animal=>"rat", :clothes=>"glove"}]
    

    【讨论】:

    • 3 来自哪里?
    • 对于他的情况,通过检查 list 获取 3。他可以通过一些必需的逻辑从list 动态获取它。如果需要,我也会提供:)
    【解决方案2】:

    利用Array#transposeArray#to_h

    keys = list.keys
    list.values.transpose.map { |v| keys.zip(v).to_h }
    

    【讨论】:

    • 类似keys = list.keys; list.values.transpose.map { |v| [keys, v].transpose.to_h }
    • 不相似,更像是,我为什么不只映射值...:p 我会更新,谢谢
    【解决方案3】:

    一体化:

    list.map{|k,v| [k].product(v)}.transpose.map(&:to_h)
    

    这个想法是使用每个关键产品的值,映射,转置,然后通过to_h转换为哈希。

    【讨论】:

    • 1. mapcollect 更惯用 2. each_pair 是多余的。
    【解决方案4】:
    [list.keys].product(list.values.transpose).map { |a| a.transpose.to_h }
       #=> [{:letter=>"a", :number=>"one", :fruit=>"apple", :car=>"vw", 
       #     :state=>"la", :color=>"red", :tree=>"oak", :animal=>"cat",
       #     :clothes=>"tie"},
       #    {:letter=>"b", :number=>"two", :fruit=>"pear", :car=>"mb",
       #     :state=>"ny", :color=>"white", :tree=>"pine", :animal=>"dog",
       #     :clothes=>"sock"},
       #    {:letter=>"c", :number=>"three", :fruit=>"kiwi", :car=>"bmw",
       #     :state=>"fl", :color=>"black", :tree=>"maple", :animal=>"rat", 
       #     :clothes=>"glove"}]
    

    假设list 定义如下。

    list = {
      letter:  ['a',     'b'   ],
      number:  ['one',   'two' ],
      fruit:   ['apple', 'pear'],
      car:     ['vw',    'mb'  ]
    }
    

    步骤如下。

    b = [list.keys]
      #=> [[:letter, :number, :fruit, :car]]
    c = list.values
      #=> [["a", "b"], ["one", "two"], ["apple", "pear"], ["vw", "mb"]]
    d = c.transpose
      #=> [["a", "one", "apple", "vw"],
      #    ["b", "two", "pear",  "mb"]]
    e = b.product(d)
      #=> [[[:letter, :number, :fruit, :car], ["a", "one", "apple", "vw"]],
      #    [[:letter, :number, :fruit, :car], ["b", "two", "pear",  "mb"]]]
    e.map { |a| a.transpose.to_h }
      #=> [{:letter=>"a", :number=>"one", :fruit=>"apple", :car=>"vw"},
      #    {:letter=>"b", :number=>"two", :fruit=>"pear",  :car=>"mb"}]
    

    让我们更仔细地看看最后一步。 mape 的第一个元素传递给块,并将块变量a 设置为其值:

    a = e.first
      #=> [[:letter, :number,  :fruit,  :car],
      #    ["a",     "one",    "apple", "vw"]]
    

    块计算如下。

    f = a.transpose
      #=> [[:letter, "a"], [:number, "one"], [:fruit, "apple"], [:car,   "vw"]]
    f.to_h
      #=> {:letter=>"a", :number=>"one", :fruit=>"apple", :car=>"vw"}
    

    e.map { |a| a.transpose.to_h } 的其余计算类似。

    【讨论】:

    • 这类似于@Marcin 的回答。主要区别是我用Array#productArray#transpose而不是Enumerable#zip,后者是阴阳。
    • @mechnicov,感谢您的称赞,也感谢您提到了混淆列表的问题。我修好了。
    【解决方案5】:

    只是为了玩Enumerable#each_with_object

    list.values.transpose.each_with_object([]) { |v, a| a << v.each_with_index.with_object({}) { |(vv, i), h| h[list.keys[i]] = vv } }
    

    【讨论】:

      猜你喜欢
      • 2019-10-27
      • 2012-10-29
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      相关资源
      最近更新 更多