在ruby中将一个哈希转换为另一个哈希

时间:2013-08-19 17:36:55

标签: ruby ruby-on-rails-3

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

{["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,因为用户发布了 只有一个帐户(“789”),即使有5个帖子{["2013-08-09", "user1"]=>1}

5 个答案:

答案 0 :(得分:3)

使用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添加到扩展程序库,这是一个非常常见的抽象。

答案 1 :(得分:2)

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

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}

答案 2 :(得分: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 :(得分:1)

  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。

答案 4 :(得分:1)

可以使用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}