2013-04-03 2 views
1

Я изучаю Структуры. Каждая структура имеет только два значения: идентификатор продукта и количество. Например:Можно ли суммировать массив структур по ключевому значению в Ruby?

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 

Сортировку в порядке убывания по количеству будет плюсом. Вот код, который я использую для создания массива структуры в вопросе:

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) 

ответ

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>] 
+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 
+0

Может быть, я толстый, но я пробовал это, и это не сработало; отредактированный вопрос, чтобы показать кодирование, используемое для создания массива struct. –

0

Enumerable#group_by и Enumerable#reduce позволяют сделать это очень просто:

EDIT: Имя класса: 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>] 
Смежные вопросы