如何在Ruby中组合类似数据的数组?

时间:2011-11-15 21:38:54

标签: ruby arrays csv

我正在开发一个比较两个.csv文件的程序。在将其中一个csv文件中的相关数据提取到数组数组后,我需要组合相关的条目。例如,我想转这个数组:

[["11/13/15", ["4001", "1392"], "INBOUND"], 
["11/13/15", ["4090", "540"], "INBOUND"], 
["11/13/15", ["1139", "162"], "INBOUND"], 
["11/13/15", ["1158", "64"], "INBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["4055", "448"], "OUTBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["1139", "162"], "OUTBOUND"], 
["11/13/15", ["1158", "64"], "OUTBOUND"], 
["11/13/15", ["4091", "520"], "OUTBOUND"]]

进入这个:

[["11/13/15", ["4001", "1392"], "INBOUND"], 
["11/13/15", ["4090", "540"], "INBOUND"], 
["11/13/15", ["1139", "162"], "INBOUND"], 
["11/13/15", ["1158", "64"], "INBOUND"], 
["11/13/15", ["4055", "1152"], "OUTBOUND"], 
["11/13/15", ["1139", "162"], "OUTBOUND"], 
["11/13/15", ["1158", "64"], "OUTBOUND"], 
["11/13/15", ["4091", "520"], "OUTBOUND"]]

对于数组的某些元素,如果[0][1][0][2]中的项与其他项相匹配,则创建一个新项(数组)及其项目位于[1][1][1][1]处所有项目的总和,并删除旧数组。如果它更容易,我可以更改提取相关数据的方式,以便[1]中的项不是数组,每行有4个项而不是3个。

4 个答案:

答案 0 :(得分:2)

我假设要分组的元素是连续的,因此我们可以使用Enumerable#chunk。功能方法:

grouped_xs = xs.chunk { |date, (id1, id2), direction| [date, id1, direction] }
grouped_xs.map do |(date, id1, direction), ary|
  id2_sum = ary.map { |date, (id1, id2), direction| id2.to_i }.inject(:+)
  [date, id1, id2_sum.to_s, direction]
end

输出(你想要输出数组中有4个元素,对吧?):

[["11/13/15", "4001", "1392", "INBOUND"],
 ["11/13/15", "4090", "540", "INBOUND"],
 ["11/13/15", "1139", "162", "INBOUND"],
 ["11/13/15", "1158", "64", "INBOUND"],
 ["11/13/15", "4055", "1152", "OUTBOUND"],
 ["11/13/15", "1139", "162", "OUTBOUND"],
 ["11/13/15", "1158", "64", "OUTBOUND"],
 ["11/13/15", "4091", "520", "OUTBOUND"]]

答案 1 :(得分:2)

仅举例来说 - 我的单行(适用于1.8和1.9红宝石):

table = [["11/13/15", ["4001", "1392"], "INBOUND"], 
["11/13/15", ["4090", "540"], "INBOUND"], 
["11/13/15", ["1139", "162"], "INBOUND"], 
["11/13/15", ["1158", "64"], "INBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["4055", "448"], "OUTBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["1139", "162"], "OUTBOUND"], 
["11/13/15", ["1158", "64"], "OUTBOUND"], 
["11/13/15", ["4091", "520"], "OUTBOUND"]]

result = table.group_by {|a, (b, c), d| [a, [b], d]}.map {|k, v| k[1] << v.map {|a| a[1][1].to_i}.inject(:+).to_s; k}

答案 2 :(得分:0)

这应该这样做:

def lookup(list, id, direction)
  index = nil
  list.each_with_index do |e, i|
    if (id == e[1][0]) and (e[2] == direction)
      index = i
      break
    end
  end
  index
end

b = []

a.each do |e|
  id = e[1][0]
  direction = e[2]
  i = lookup(b, id, direction)
  if i.nil?
    b << e
  else
    count = e[1][1].to_i
    sum = count + b[i][1][1].to_i
    b[i][1][1] = sum.to_s
  end
end

b.each{|e| p e}

输出:

["11/13/15", ["4001", "1392"], "INBOUND"]
["11/13/15", ["4090", "540"], "INBOUND"]
["11/13/15", ["1139", "162"], "INBOUND"]
["11/13/15", ["1158", "64"], "INBOUND"]
["11/13/15", ["4055", "1152"], "OUTBOUND"]
["11/13/15", ["1139", "162"], "OUTBOUND"]
["11/13/15", ["1158", "64"], "OUTBOUND"]
["11/13/15", ["4091", "520"], "OUTBOUND"]

答案 3 :(得分:0)

h = Hash.new(0)
[["11/13/15", ["4001", "1392"], "INBOUND"], 
["11/13/15", ["4090", "540"], "INBOUND"], 
["11/13/15", ["1139", "162"], "INBOUND"], 
["11/13/15", ["1158", "64"], "INBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["4055", "448"], "OUTBOUND"], 
["11/13/15", ["4055", "352"], "OUTBOUND"], 
["11/13/15", ["1139", "162"], "OUTBOUND"], 
["11/13/15", ["1158", "64"], "OUTBOUND"], 
["11/13/15", ["4091", "520"], "OUTBOUND"]]
.each{|a, (b, c), d| h[[a, b, d]] += c.to_i}
p h.map{|(a, b, d), c| [a, [b, c], d]}

会给:

[["11/13/15", ["4001", 1392], "INBOUND"],
["11/13/15", ["4090", 540], "INBOUND"],
["11/13/15", ["1139", 162], "INBOUND"],
["11/13/15", ["1158", 64], "INBOUND"],
["11/13/15", ["4055", 1152], "OUTBOUND"],
["11/13/15", ["1139", 162], "OUTBOUND"],
["11/13/15", ["1158", 64], "OUTBOUND"],
["11/13/15", ["4091", 520], "OUTBOUND"]]