【问题标题】:Converting one hash to another hash in ruby在 ruby​​ 中将一个哈希转换为另一个哈希
【发布时间】:2013-08-19 17:36:54
【问题描述】:

将以下哈希转换为另一个哈希。

{["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789", "user1"]=>5} 

将上面的哈希转换为

{["2013-08-15", "user1"]=>2, ["2013-08-09", "user1"]=>1} 

如您所见,哈希中的第一个和第二个键值对具有相同的日期, 不同的帐户和相同的用户,在这种情况下我需要计算总数 用户帖子为两个{["2013-08-15", "user1"]=>2}

在最后一个键值对中,计数应该是 1,因为用户发布到 尽管有 5 个帖子 {["2013-08-09", "user1"]=>1},但只有一个帐户(“789”)。

【问题讨论】:

  • @mbratch 当然可以。 IIRC 任何响应 hasheql? 的对象都可以用作哈希键。
  • @mbratch 当然可以。 {[1] => 'foo'}[[1]] 返回foo

标签: ruby ruby-on-rails-3


【解决方案1】:

使用Facets'Enumerable#frequency,您可以编写这个干净且模块化的单行代码:

require 'facets'
hash1 = {["2013-08-15", "123", "user1"] => 1, ...}
hash2 = hash1.keys.map { |date, code, user| [date, user] }.frequency
#=> {["2013-08-15", "user1"] => 2, ["2013-08-09", "user1"] => 1}

请注意,解包数组的值可以更容易地查看发生了什么。另外请注意,您不需要依赖 Facets,只需将 Enumerable#frequency 添加到您的扩展库中,这是一个非常常见的抽象。

【讨论】:

  • 我收到了这个错误 hash1.keys.map { |date, code, user| [日期,用户] }.frequency NoMethodError: #<0x007fdc2e813208>
【解决方案2】:
h = {["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789","user1"]=>5} 
Hash[h.group_by{|k,v| k[0]}.map{|_,v| [v.flatten.values_at(0,2),v.size]}]
# => {["2013-08-15", "user1"]=>2, ["2013-08-09", "user1"]=>1}

或者,

h = {["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789","user1"]=>5} 
h.each_with_object(Hash.new(0)){|((d,_,u),_),hsh| hsh[[d,u]] +=1 }
# => {["2013-08-15", "user1"]=>2, ["2013-08-09", "user1"]=>1}

【讨论】:

    【解决方案3】:

    不是很优雅,但很有效。另外,使用数组作为哈希键有点奇怪。

    h = {["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789", "user1"]=>5}
    h.inject(Hash.new(0)){|a,((date,post,user),v)| a[[date,user]] +=1; a } # => {["2013-08-15", "user1"]=>2, ["2013-08-09", "user1"]=>1}
    

    【讨论】:

      【解决方案4】:
        hash1 = {["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789", "user1"]=>5} 
      
        hash2 = Hash.new
        hash1.each do |x,y|
            hash2[ [x[0],x[2]] ] = hash2[ [x[0],x[2]] ].to_i + 1
        end
        puts hash2
      

      请注意,您需要使用 .to_i 方法进行首次初始化,否则我们将使用 nil 添加,但这会使其为 0。

      【讨论】:

        【解决方案5】:

        这可以通过group_bymap 完成:

        h = {["2013-08-15", "123", "user1"]=>1, ["2013-08-15", "456", "user1"]=>1, ["2013-08-09", "789", "user1"]=>5}
        
        Hash[h.group_by { |(u, _, d), _| [u, d] }.map { |u, d| [u, d.size] }]
        #=> {["2013-08-15", "user1"]=>2, ["2013-08-09", "user1"]=>1}
        

        【讨论】:

        • +1。注意:尽管我很喜欢 FP,其中使用 _ 来表示“随便”是一种常见的习惯用法,但我更喜欢为未使用的变量命名,这样更清楚。至少在 Ruby 中它看起来很奇怪。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        • 2013-07-21
        • 1970-01-01
        • 2012-07-15
        • 1970-01-01
        • 2017-07-06
        • 2012-11-19
        相关资源
        最近更新 更多