是否可以通过Ruby中的键值对结构数组求和?

时间:2013-04-03 20:55:45

标签: ruby arrays sorting struct sum

我正在探索Structs。每个结构只有两个值:产品ID和数量。例如:

prodcode = 2473 , quantity = 1
prodcode = 2473 , quantity = 4
prodcode = 3328 , quantity = 6
prodcode = 2958 , quantity = 3
prodcode = 2473 , quantity = 7
prodcode = 2958 , quantity = 2
prodcode = 2473 , quantity = -1

我想得到像这样的结构数量的总和:

prodcode = 2473 , quantity = 11
prodcode = 3328 , quantity = 6
prodcode = 2958 , quantity = 5

按数量降序排序将是一个加号。这是我用来创建有问题的struct数组的代码:

class Figs < Struct.new(:prodcode, :quantity)  
  def print_csv_record  
    prodcode.length==0 ? printf(",") : printf(prodcode)  
    quantity.length==0 ? printf(",") : printf(",", quantity.to_i)  
    printf("\n")  
  end  
end  

...  

for x in 0...global.length  
  p = Figs.new  
  p.prodcode = global[x][0]  
  p.quantity = global[x][1].to_i  
  figures.push(p)  
end

Struct数组是“数字”,但我得到了

undefined local variable or method 'quantity' for main:Object (NameError)

3 个答案:

答案 0 :(得分:0)

您可以使用哈希来聚合新结构中的数量:

MyStruct = Struct.new(:prodcode, :quantity)

struct_array.inject({}) do |m, s| 
  m[s.prodcode] ||= MyStruct.new(s.prodcode, 0)
  m[s.prodcode].quantity += quantity
  m
end.values

答案 1 :(得分:0)

比PinnyM的回答更加冗长,但无论如何,这里有一条相同的建议。 :-D

Product = Struct.new(:code, :quantity)

a = Product.new(100, 1)
b = Product.new(100, 3)
c = Product.new(100, 1)

d = Product.new(200, 2)
e = Product.new(200, 2)

products = [a, b, c, d, e] # start
results = {}               # for temporary counting
product_sums = []          # for creating the end structs

products.each do |product|
 results[product.code] ||= 0
 results[product.code] += product.quantity
end

p results
# => {100=>5, 200=>4}

results.each do |code, quantity|
  product_sums << Product.new(code, quantity)
end

p product_sums
# => [#<struct Product code=100, quantity=5>, #<struct Product code=200, quantity=4>]

答案 2 :(得分:0)

Enumerable#group_byEnumerable#reduce让您可以非常简单地执行此操作:

编辑:使用OP的类名,按降序数添加排序和清洁print_csv方法

require 'csv'

class Figs < Struct.new(:prodcode, :quantity)
  def print_csv_record
    print to_a.to_csv
  end
end

a = [Figs[2473,1], Figs[2473,4], Figs[3328,6], Figs[2958,3],
     Figs[2473,7], Figs[2958,2], Figs[2473,-1]]

a.group_by(&:prodcode).
  map { |k,v| Figs[ k, v.map(&:quantity).reduce(:+) ] }.
  sort_by { |e| -e.quantity }

=> [#<struct Figs prodcode=2473, quantity=11>,
    #<struct Figs prodcode=3328, quantity=6>,
    #<struct Figs prodcode=2958, quantity=5>]