【问题标题】:How do I add values from two different arrays of hashes together?如何将两个不同的哈希数组中的值相加?
【发布时间】:2010-12-08 11:38:59
【问题描述】:

我有两个哈希数组。哈希的键不同:

player_scores1 = [{:first_name=>"Bruce", :score => 43, :time => 50},
                  {:first_name=>"Clark", :score => 45, :minutes => 20}]

player_scores2 = [{:last_name=>"Wayne", :points => 13, :time => 40},
                  {:last_name=>"Kent", :points => 3, :minutes => 20}]

我想创建一个新的哈希数组,将 :score 和 :points 加起来,并将其分配给一个名为 :score 的键。我还想组合 :first_name 和 :last_name 并将其分配给一个名为 :full_name 的键。我想丢弃任何其他键。

这将导致这个数组:

all_players = [{:full_name => "Bruce Wayne", :score => 56}, 
               {:full_name => "Clark Kent", :score => 48}]

有没有优雅的方法来做到这一点?

【问题讨论】:

    标签: ruby arrays hash


    【解决方案1】:

    类似这样的:

    player_scores1.zip(player_scores2).map { |a,b|
        {
            :full_name => a[:first_name]+' '+b[:last_name],
            :score => a[:score]+b[:points]
        }
    }
    

    【讨论】:

    • 酷,没听说过zip方式!
    • 这个函数en.wikipedia.org/wiki/Convolution_(computer_science)存在于很多语言中:Python、Haskell...
    • +1,但我认为在多行块上使用 do-end 是惯用的 Ruby。
    • @tokland, {} != do end。有时你需要{}。例如,当我测试这段代码时,我在它前面粘贴了p。使用do end 它将返回枚举器并像<#Enumerator... 一样打印smth 而不是数组。
    • @Nakilon 你用的是什么版本的红宝石?在 1.8.7 上使用 do end 对我来说工作正常
    【解决方案2】:

    您要查找的代码是:

    final = []
    player_scores1.each_index do |index|
      entry_1 = player_scores1.values(index)
      entry_2 = player_scores2.values(index)[:first_name]
      score = entry_1[:score] + entry_2[:points]
      final << {:full_name => "#{entry_1[:first_name]} #{entry_2[:last_name]}", :score => score }
    end
    

    任何关于加强这一点的建议将不胜感激!

    【讨论】:

    • 刚试了一下,报错:"NoMethodError: undefined method 'merge' for #&lt;Array:0x102cef1a0&gt; from (irb):15 "
    • 重读问题——我的答案错了,让我重做。
    【解决方案3】:

    这行得通。不过,如果这足够优雅,我不会。

    player_scores1 = [{:first_name=>"Bruce", :score => 43, :time => 50},
                      {:first_name=>"Clark", :score => 45, :minutes => 20}]
    
    player_scores2 = [{:last_name=>"Wayne", :points => 13, :time => 40},
                      {:last_name=>"Kent", :points => 3, :minutes => 20}]
    
    p (0...[player_scores1.length, player_scores2.length].min).map {|i| {
        :full_name => player_scores1[i][:first_name] + " " + player_scores2[i][:last_name], 
        :score => player_scores1[i][:score] + player_scores2[i][:points]
    }}
    

    Codepad 上的这个例子。

    【讨论】:

      【解决方案4】:

      这使用 zip 和一个块来循环哈希,连接名称并总结:

      all_players = []
      player_scores1.zip(player_scores2) { |a, b| 
        all_players << { 
          :full_name => a[:first_name] + ' ' + b[:last_name],
          :score     => a[:score] + b[:points]
        } 
      }
      all_players # => [{:full_name=>"Bruce Wayne", :score=>56}, {:full_name=>"Clark Kent", :score=>48}]
      

      【讨论】:

      • 初始化一个空数组 + 在循环中追加值 + 返回数组 = map
      • 通常。这通过让 zip 块来完成人们对zip.each 所做的通常的额外步骤。由于 zip 已经对它们中的每一个进行了循环,因此对哈希进行再次迭代是没有意义的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-30
      • 1970-01-01
      • 2019-05-03
      • 2015-12-05
      • 2013-03-29
      相关资源
      最近更新 更多