2016-08-16 15 views
0

У меня после ввода:Преобразование Руби Хэши Сортировать массив Hash

array = [{:year=>2015, :platform_id=>2}, 
     {:year=>nil, :platform_id=>2}, 
     {:year=>nil, :platform_id=>4}, 
     {:year=>2015, :platform_id=>4}] 

мне нужно ожидаемый результат будет:

[{platform_id=>2, year=>[2015, nil]}, 
{platform_id=>4, year=>[nil, 2015]}] 

Что я код:

array.inject(:merge) 

Но это дает мне этот результат, который не то, что я хочу:

{:year=>2015, :platform_id=>4} 

Обновлено ниже после того, как ответ получил:

Я тест производительности после увидеть ответы и вот результат:

arr = [ 
    {:year => 2015, :platform_id => 2}, 
    {:year => nil, :platform_id => 2}, 
    {:year => nil, :platform_id => 4}, 
    {:year => 2015, :platform_id => 4} 
] 

#approach 1 
x1 = Time.now.to_f 
exp = arr.each_with_object({}) do |h, exp| 
    exp[h[:platform_id]] ||= {:platform_id => h[:platform_id], :year => []} 
    exp[h[:platform_id]][:year] << h[:year] 
end.values 
x2 = Time.now.to_f 
p x2-x1 

#approach 2 
x3 = Time.now.to_f 
new_data = arr.group_by { |d| d[:platform_id] } 
new_arr = [] 
new_data.each do |k,v| 
t2 = v.map{|x| x[:year]} 
temp = {"platform_id": k, "years": t2} 
new_arr.push(temp) 
end 
x4 = Time.now.to_f 
p x4-x3 

#approach 3 
x5 = Time.now.to_f 
f = arr.each_with_object({}) { |g,h| 
    h.update(g[:platform_id]=>[g[:year]]) { |_,o,n| o+n } } 
    #=> {2=>[2015, nil], 4=>[nil, 2015]} 

f.map { |k,v| { :platform_id=>k, :year=>v } } 
x6 = Time.now.to_f 
p x6-x5 

#output is: 
9.059906005859375e-06 
6.4373016357421875e-06 
9.775161743164062e-06 
+4

Если вы просто хотите, чтобы код был выполнен, вы должны нанять программиста, чтобы сделать это за вас. Но если вы хотите научиться решать эту задачу самостоятельно, вы должны попробовать как можно больше и показать нам свой прогресс и вашу проблему. – Gabriel

+0

Я пробовал инъекцию, уменьшаю, но оба дают только первое значение. Я не уверен, что случилось с этими функциями. –

+1

не могли бы вы обновить свой вопрос с помощью вашего фактического требования? Каково ваше требование изменить «год»? Если вы просто хотите заказать свой массив хэш, вы можете использовать 'sort_by' с ключом. – Aparichith

ответ

2
arr = [ 
    { :year=>2015, :platform_id=>2 }, 
    { :year=>nil, :platform_id=>2 }, 
    { :year=>nil, :platform_id=>4 }, 
    { :year=>2015, :platform_id=>4 } 
] 

arr.each_with_object({}) { |g,h| 
    h.update(g[:platform_id]=>[g[:year]]) { |_,o,n| o+n } }. 
    map { |k,v| { :platform_id=>k, :year=>v } } 
    #=> [{:platform_id=>2, :year=>[2015, nil]}, 
    # {:platform_id=>4, :year=>[nil, 2015]}] 

Эти два шага являются следующими.

f = arr.each_with_object({}) { |g,h| 
    h.update(g[:platform_id]=>[g[:year]]) { |_,o,n| o+n } } 
    #=> {2=>[2015, nil], 4=>[nil, 2015]} 

f.map { |k,v| { :platform_id=>k, :year=>v } } 
    #=> [{:platform_id=>2, :year=>[2015, nil]}, 
    # {:platform_id=>4, :year=>[nil, 2015]}] 

Первый шаг использует форму Hash#update (он же merge!), который использует блок (здесь { |_,o,n| o+n }), который вычисляет значение клавиш, которые присутствуют в обоих хешей быть объединены.

+0

Поблагодарили Cary за подробный ответ. –

0

Вот ответ:

data = [ 
{:year=>2015, :platform_id=>2}, 
{:year=>nil, :platform_id=>2}, 
{:year=>nil, :platform_id=>4}, 
{:year=>2015, :platform_id=>4} 
] 

new_data = data.group_by { |d| d[:platform_id] } 


#p new_data 

new_arr = [] 

new_data.each do |k,v| 
t2 = v.map{|x| x[:year]} 
temp = {"pf_id": k, "years": t2} 
new_arr.push(temp) 
end 

p new_arr 
+0

Вы находитесь на правильном пути здесь с 'group_by', но помните, что' map' отлично подходит для преобразования одного массива в другой, сохраняя 'x = []; y.each ... x.push (...) 'часть. – tadman

2

Вы можете использовать each_with_object с хешем и напечатать значения, подобные этому

arr = [ 
    {:year => 2015, :platform_id => 2}, 
    {:year => nil, :platform_id => 2}, 
    {:year => nil, :platform_id => 4}, 
    {:year => 2015, :platform_id => 4} 
] 

exp = arr.each_with_object({}) do |h, exp| 
    exp[h[:platform_id]] ||= {:platform_id => h[:platform_id], :year => []} 
    exp[h[:platform_id]][:year] << h[:year] 
end.values 

p exp 
# => [{:platform_id=>2, :year=>[2015, nil]}, {:platform_id=>4, :year=>[nil, 2015]}] 
+0

Спасибо, анализируя более оптимизированный код Lukas and Carry –

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