Сортировка и сохранение значений из многомерного массива в новом массиве в Ruby - PullRequest
0 голосов
/ 23 октября 2009

У меня есть следующий массив:

votes_array = [["2", "1"], ["2", "4"], ["4", "3"], ["3", "4"], ["1", "N"], ["3", "1"], ["1", "2"], ["4", "1"], ["0", "1"], ["0", "2"], ["1", "3"], ["1", "4"]]

И я хочу создать новый массив (или хэш), который будет хранить элементы voice_array по их первому варианту, чтобы новый массив выглядел так:

candidate_votes = [
                   {"id" => "0", "votes" => [["0", "1"],["0","2"]]}, 
                   {"id" => "1", "votes" => [["1", "N"],["1","2"],["1","3"],["1","4"]]},
                   etc,
                   etc]

Порядок голосов в ключе голосования не важен, просто все голоса разделены на соответствующие идентификаторы.

Я работаю со следующим кодом:

first_preferences = votes_array.map(&:first)
valid_candidates = first_preferences.uniq
valid_candidates.each do |candidate|
   these_votes = votes_array.find_all { |i| i[0] == candidate }
   candidate_votes << {"id" => candidate, "votes" => these_votes}
end  

Но интересно, есть ли более элегантный, чище или Rubiyst способ?

Ответы [ 3 ]

4 голосов
/ 23 октября 2009

С Ruby 1.8.7+, это однострочный:

candidate_votes = votes_array.group_by {|pair| pair[0]}

Красивая печать candidate_votes Возвращает

{"0"=>[["0", "1"], ["0", "2"]],
 "1"=>[["1", "N"], ["1", "2"], ["1", "3"], ["1", "4"]],
 "2"=>[["2", "1"], ["2", "4"]],
 "3"=>[["3", "4"], ["3", "1"]],
 "4"=>[["4", "3"], ["4", "1"]]}
1 голос
/ 23 октября 2009

Вот тот, который создает candidate_votes как хэш. Вероятно, это немного быстрее, потому что вам нужно повторить votes_array только один раз:

candidate_votes = {}
votes_array.each do |id, vote|
  candidate_votes[id] ||= {"id" => id, "votes" => []}
  candidate_votes[id]["votes"] << [id, vote]
end

Это даст такие результаты:

candidate_votes = {
                    "0" => {"votes" => [["0", "1"], ["0", "2"]], "id" => "0"},
                    ... etc ...
                  }
0 голосов
/ 23 октября 2009

Я думаю, что вы можете организовать вывод гораздо более кратко, используя что-то вроде этого:

# Use Enumerable#inject to convert Array to Hash
results = votes_array.inject({ }) do |hash, vote|
  # Create hash entry for candidate if not defined (||=)
  hash[vote[0]] ||= { :votes => [ ] }

  # Add vote to candidate's array of votes
  hash[vote[0]][:votes] << vote[1]

  # Keep hash for next round of inject
  hash
end

# => {"0"=>{:votes=>["1", "2"]}, "1"=>{:votes=>["N", "2", "3", "4"]}, "2"=>{:votes=>["1", "4"]}, "3"=>{:votes=>["4", "1"]}, "4"=>{:votes=>["3", "1"]}}

Как примечание, для Ruby выгодно использовать символы для хэш-ключей, поскольку они обычно более эффективны, чем строки для такого рода приложений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...