在Ruby中整合多维数组

时间:2015-07-13 19:54:46

标签: arrays ruby

我有一系列"投票"在另一个数组中设置为[ID,Rating]

[["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "4"],
 ["1250", "5"],
 ["1250", "5"],
 ["1252", "2"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "3"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "4"],
 ["1254", "5"],
 ["1254", "4"],
 ["1254", "4"],
 ["1257", "5"],
 ["1257", "5"],
 ["1257", "4"],
 ["1257", "5"],
 ...]

我希望合并x的倍数,并保留与x相关的所有y。基本上我必须对特定id(x)的所有投票(y)进行平均,并且我不确定如何做到这一点。此外,这些投票(y)必须是"加权"以后会有不同的数额,所以我认为保持对它们的访问将会有所帮助。

坦率地说,我甚至不知道这叫什么,所以不知道要查找什么:/我尝试合并,将y推到数组[x]上,有些复杂&# 39;对于唯一的x do | y |'。只是难以理解如何处理这个问题。

最终目标可能是这样的:

[["1250", ["5", "5", "5", "4", "5", "5"]],
 ["1252", ["2", "5", "4", "3", "5", "4", "4"]],
 ["1254", ["5", "4", "4"]],
 ["1257", ["5", "5", "4", "5"]],
...]

6 个答案:

答案 0 :(得分:3)

一个简短的解决方案。

my_array = [ .... ]
my_array.group_by(&:first).map { |k,v| [k, v.map { |_,y| [y] }.reduce(:+)] }

它使用了可枚举方法group_by()map()reduce()

编辑:附加说明

通过较小的自适应,上述解决方案也会累积ys的值。我猜这是问题的主要内涵,但不是。

my_array.group_by(&:first).map { |k,v| [k, v.map { |_,y| y.to_i }.reduce(:+)] }

答案 1 :(得分:1)

我会做这样的事情:

array.group_by(&:first).map { |k, v| [k, v.map(&:last)] }

答案 2 :(得分:1)

也许你可以用哈希来做到这一点。

votes= [["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "4"],
 ["1250", "5"],
 ["1250", "5"],
 ["1252", "2"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "3"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "4"],
 ["1254", "5"],
 ["1254", "4"],
 ["1254", "4"],
 ["1257", "5"],
 ["1257", "5"],
 ["1257", "4"],
 ["1257", "5"]]


resume={}

votes.each do |vote|
  resume[vote[0]]=[] unless resume.include?(vote[0])
  resume[vote[0]] << vote[1]
end

puts resume.to_s

然后你可以用那个哈希做任何你想做的事。

答案 3 :(得分:1)

[["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "5"],
 ["1250", "4"],
 ["1250", "5"],
 ["1250", "5"],
 ["1252", "2"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "3"],
 ["1252", "5"],
 ["1252", "4"],
 ["1252", "4"],
 ["1254", "5"],
 ["1254", "4"],
 ["1254", "4"],
 ["1257", "5"],
 ["1257", "5"],
 ["1257", "4"],
 ["1257", "5"]]

hsh = Hash.new{|h,k| h[k] = []} 
# hsh stores the key with an empty array if it does not "know" a key
votes.each_with_object(hsh){|(id, vote), h| h[id] << vote}
# add vote to the array when hsh "knows" the key.

p hsh
# =>{"1250"=>["5", "5", "5", "5", "4", "5", "5"], "1252"=>["2", "5", "4", "3", "5", "4", "4"]...}

答案 4 :(得分:1)

假设您的数组按照每个(双元素数组)投票元素的第一个元素排序,就像在示例中一样,您可以使用我们在v.2.2中给出的Enumerable#slice_when

votes.slice_when { |(v1,_),(v2,_)| v1 != v2 }
     .each_with_object({}) { |a,h| h[a.first.first] = a.map(&:last) }
  #=> {"1250"=>["5", "5", "5", "5", "4", "5", "5"],
  #    "1252"=>["2", "5", "4", "3", "5", "4", "4"],
  #    "1254"=>["5", "4", "4"],
  #    "1257"=>["5", "5", "4", "5"]} 

其中:

votes =
[["1250", "5"],
 ["1250", "5"],
 ...
 ["1257", "4"],
 ["1257", "5"]]

答案 5 :(得分:0)

您可以构建一个Hash,其中ID是键,值可以是一个等级数组:

table = Hash.new()
list.each do |id_rating_pair|
  id = id_rating_pair[0]to_sym
  rating = id_rating_pair[1].to_i

  if !table.has_key?( id )
    table[id] = Array.new()
  end

  table[id].push( rating )
end

现在使用此表您可以执行统计信息。

我知道它不短,但很清楚,可以根据您的需要进行修改。