2015-07-13 5 views
1

У меня есть массив «голоса», установленные в [ID, Рейтинг] внутри другого массиваЗакрепление многомерного массива в Рубине

[["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "4"], 
["1250", "5"], 
["1250", "5"], 
["1252", "2"], 
["1252", "5"], 
["1252", "4"], 
["1252", "3"], 
["1252", "5"], 
["1252", "4"], 
["1252", "4"], 
["1254", "5"], 
["1254", "4"], 
["1254", "4"], 
["1257", "5"], 
["1257", "5"], 
["1257", "4"], 
["1257", "5"], 
...] 

Есть кратные х, которые я хочу, чтобы объединить и сохранить все у этого отношение к что x доступно. В основном я должен усреднять все голоса (y) для определенного id (x) и не знаю, как это сделать. Кроме того, эти голоса (y) должны быть «взвешены» разными суммами позже, поэтому я думаю, что доступ к ним был бы полезен в будущем.

Откровенно говоря, я даже не знаю, как это называется, поэтому не знаю, что искать:/Я попытался слить, нажав y на массив [x] и немного сложный для уникального x do | y | , Просто тупик о том, как справиться с этой проблемой.

End цель может быть что-то вроде этого:

[["1250", ["5", "5", "5", "4", "5", "5"]], 
["1252", ["2", "5", "4", "3", "5", "4", "4"]], 
["1254", ["5", "4", "4"]], 
["1257", ["5", "5", "4", "5"]], 
...] 
+1

Я думаю, что было бы полезно, чтобы увидеть минимальный пример ввода и ожидаемого результата. – spickermann

+0

Несомненно, я обновлю вопрос – victoroux

ответ

1
[["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "4"], 
["1250", "5"], 
["1250", "5"], 
["1252", "2"], 
["1252", "5"], 
["1252", "4"], 
["1252", "3"], 
["1252", "5"], 
["1252", "4"], 
["1252", "4"], 
["1254", "5"], 
["1254", "4"], 
["1254", "4"], 
["1257", "5"], 
["1257", "5"], 
["1257", "4"], 
["1257", "5"]] 

hsh = Hash.new{|h,k| h[k] = []} 
# hsh stores the key with an empty array if it does not "know" a key 
votes.each_with_object(hsh){|(id, vote), h| h[id] << vote} 
# add vote to the array when hsh "knows" the key. 

p hsh 
# =>{"1250"=>["5", "5", "5", "5", "4", "5", "5"], "1252"=>["2", "5", "4", "3", "5", "4", "4"]...} 
3

Одно короткое решение.

my_array = [ .... ] 
my_array.group_by(&:first).map { |k,v| [k, v.map { |_,y| [y] }.reduce(:+)] } 

Он использует перечислимую методу group_by(), map(), reduce().

РЕДАКТИРОВАТЬ: Дополнительные примечания

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

my_array.group_by(&:first).map { |k,v| [k, v.map { |_,y| y.to_i }.reduce(:+)] } 
+0

Проблема заключается в том, что он объединяет все значения и связывает их с id (тогда как мне нужно среднее значение). Вы дали мне хорошие идеи, чтобы заглянуть - спасибо! – victoroux

1

Я хотел бы сделать что-то вроде этого:

array.group_by(&:first).map { |k, v| [k, v.map(&:last)] } 
1

Может быть, вы можете сделать это с помощью хэш.

votes= [["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "5"], 
["1250", "4"], 
["1250", "5"], 
["1250", "5"], 
["1252", "2"], 
["1252", "5"], 
["1252", "4"], 
["1252", "3"], 
["1252", "5"], 
["1252", "4"], 
["1252", "4"], 
["1254", "5"], 
["1254", "4"], 
["1254", "4"], 
["1257", "5"], 
["1257", "5"], 
["1257", "4"], 
["1257", "5"]] 


resume={} 

votes.each do |vote| 
    resume[vote[0]]=[] unless resume.include?(vote[0]) 
    resume[vote[0]] << vote[1] 
end 

puts resume.to_s 

, а затем вы можете делать все, что хотите, с помощью этого хэша.

+1

Вы можете удалить дополнительные 'except', как это:' resume [vote [0]] || = [] ' – Danieth

0

Вы могли бы построить Hash где ID является ключом и значение может быть массивом оценок:

table = Hash.new() 
list.each do |id_rating_pair| 
    id = id_rating_pair[0]to_sym 
    rating = id_rating_pair[1].to_i 

    if !table.has_key?(id) 
    table[id] = Array.new() 
    end 

    table[id].push(rating) 
end 

Теперь с этой таблицей вы можете выполнить свою статистику.

Я знаю, что он не короткий, но он ясен и может быть пересмотрен в соответствии с вашими потребностями.

1

Если предположить, что массив упорядочен первым элементом каждого элемента (два-элемента массива) голосов, как в примере, вы можете использовать Enumerable#slice_when которые нам дали в v.2.2:

votes.slice_when { |(v1,_),(v2,_)| v1 != v2 } 
    .each_with_object({}) { |a,h| h[a.first.first] = a.map(&:last) } 
    #=> {"1250"=>["5", "5", "5", "5", "4", "5", "5"], 
    # "1252"=>["2", "5", "4", "3", "5", "4", "4"], 
    # "1254"=>["5", "4", "4"], 
    # "1257"=>["5", "5", "4", "5"]} 

где:

votes = 
[["1250", "5"], 
["1250", "5"], 
... 
["1257", "4"], 
["1257", "5"]] 
Смежные вопросы