2013-04-24 2 views
1

Предположим, у меня есть этот массивГруппировка с помощью элемента в хэш

x=[{:shipping_id=>2, :fsn=>"ab", :price=>300, :quantity=>1}, 
    {:shipping_id=>3, :fsn=>"abc",:price=>500, :quantity=>2}, 
    {:shipping_id=>2, :fsn=>"abcd",:price=>300,:quantity=>3}, 
    {:shipping_id=>4, :fsn=>"abx", :price=>600,:quantity=>1}, 
    {:shipping_id=>3, :fsn=>"abb", :price=>400,:quantity=>1}] 

Я хочу, чтобы сгруппировать его по уникальной доставки ид, но в этом случае давайте просто группу по shipping_id = 2

Так что я x.select! {|y| y[:shipping_id]==2}, который дает мне

[{:shipping_id=>2, :fsn=>"ab",:price=>300,:quantity=>1}, {:shipping_id=>2, :fsn=>"abcd",:price=>300,:quantity=>3}] 

Но проблема, я хочу, чтобы мой результат в этом виде

x={:shipping_id=>[2,2],:fsn=>["ab","abcd"],:price=>[300,300],:quantity=>[1,3]} 

Что мне делать? Я могу сделать это в нескольких строках, но есть ли оптимизированный способ для этого?

UPDATE -: Окончательный рабочий раствор (Мое решение) -

Контроллер

new_params={} 
order_hash.each do |row| 
     new_params=row.convert_to_params(new_params) 
end 
params.merge!(new_params) 

Модель

def convert_to_params(new_params) 
    item=self.instance_values.symbolize_keys 
    item.each do |k, v| 
     new_params[k].nil? ? new_params[k]=[v] : new_params[k].push(v) 
    end 
    return new_params 
end 

Это дало мне мой желаемый результат

+0

Я не согласен с тем, что это слишком локализовано. Я не думаю, что этот вопрос должен был быть закрыт. Существует общий алгоритм группировки, лежащий в основе вопроса, который может быть полезен другим. –

+0

@ JimStewart - Я согласен, я действительно не думаю, что это был общий вопрос. В любом случае, мне нравится то, что мое решение довольно аккуратно. –

ответ

1
arr = x= [{:shipping_id=>2, :fsn=>"ab"}, 
{:shipping_id=>3, :fsn=>"abc"}, {:shipping_id=>2, :fsn=>"abcd"}, 
{:shipping_id=>4, :fsn=>"abx"}, {:shipping_id=>3, :fsn=>"abb"}] 
@h = {} 
arr.group_by {|x| x[:shipping_id]==2 }[true].inject({}) do |mem,i| 
    i.each{|k,v| mem[k] = [v] << mem[k] ; @h = mem} 
end 
p @h #=> {:shipping_id=>[2, 2], :fsn=>["abcd", "ab"]} 
+0

Большое спасибо ... –

+0

Это больше, чем помогает .... Мне очень нравится решение. Дал бы ему 2 голоса, если бы мог. :-) –

+0

@PratikBothra Мое удовольствие! Но '@ h' играет здесь важную роль. Я потратил больше времени, чтобы получить эту работу. atlast @h помог мне. –

1

Вы могли бы do:

ret = Hash[x.group_by {|e| e[:shipping_id]}.map {|e| [e.first, e.last.map {|t| t[:fsn]}]}] 

, а затем, если вам нужны только те, для shipping_id = 2

> ret[2] 
=> ["ab", "abcd"] 
+0

Хорошая попытка, но я хочу, чтобы shipping_id тоже был в массиве, хотя они идентичны. И это выглядит довольно долго. –

+0

Итак, я получаю что-то вроде этого: {2 => ["ab", "abcd"], 3 => ["abc", "abb"], 4 => ["abx"]}. Пусть теперь группа_by. В любом случае спасибо. –

+0

@PratikBothra, нуждающийся в списке дублирующих идентификаторов доставки, является очень странным требованием. Если вы добавите некоторую информацию о домене, вы можете получить некоторые предложения о том, как лучше структурировать решение. – harbichidian

0

Отредактировано:

>> z = x.group_by {|y| y[:shipping_id] } 
#=> {2=>[{:shipping_id=>2, :fsn=>"ab"}, {:shipping_id=>2, :fsn=>"abcd"}], 3=>[{:shipping_id=>3, :fsn=>"abc"}, {:shipping_id=>3, :fsn=>"abb"}], 4=>[{:shipping_id=>4, :fsn=>"abx"}]} 

>> Hash[z.map {|k, v| Array[[k]*v.count, v] }] 
#=> {[2, 2]=>[{:shipping_id=>2, :fsn=>"ab"}, {:shipping_id=>2, :fsn=>"abcd"}], [3, 3]=>[{:shipping_id=>3, :fsn=>"abc"}, {:shipping_id=>3, :fsn=>"abb"}], [4]=>[{:shipping_id=>4, :fsn=>"abx"}]} 

Не совсем то, что вам нужно, все-таки оставить его здесь, в случае, если вы сочтете это полезным.

 Смежные вопросы

  • Нет связанных вопросов^_^