2012-03-07 2 views
5

Я хочу вывести массив хэшей с name, который является уникальным для всех хэшей. Как мне это сделать, используя рубин?Удалить дубликат из массива в ruby ​​

Это мой вход:

input = [{:name => "Kutty", :score => 2, :some_key => 'value', ...}, 
     {:name => "Kutty", :score => 4, :some_key => 'value', ...}, 
     {:name => "Baba", :score => 5, :some_key => 'value', ...}] 

Я хочу, чтобы выход выглядеть следующим образом:

output = [{:name => "Kutty", :score => 4, :some_key => 'value', ...}, 
      {:name => "Baba", :score => 5, :some_key => 'value', ...}] 
+0

я в принципе не хочу дублировать запись хэш в массив !. И я хочу, чтобы это основало больше очков. – Jak

+0

Если я правильно понимаю ваш комментарий, ваш результат не соответствует действительности. Самый высокий балл Kutty - 4. –

+0

да отметьте. Во всяком случае, я получил решение. Просто условный оператор должен измениться. Спасибо за находку. Я обновлю свои вопросы. – Jak

ответ

15

Чтобы просто удалить дубликаты на основе: имя, просто попробовать;

output = input.uniq { |x| x[:name] } 

Демо-версия here.

Edit: Поскольку вы добавили сортировочную потребность в комментариях, вот как выбрать запись с наибольшим количеством очков для каждого имени, если вы используете Rails, я вижу, вы уже получили ответ на «стандартный» Рубин выше;

output = input.group_by { |x| x[:name] } 
       .map {|x,y|y.max_by {|x|x[:score]}} 

Немного объяснений может быть в порядке; в первой строке groups записи по имени, чтобы каждое имя получало свой собственный массив записей. Вторая строка проходит через группы, имя по имени и maps каждой группе имен в записи с наивысшим баллом.

Демонстрация here.

3
input = [{:name => "Kutty", :score => 2, :some_key => 'value'},{:name => "Kutty", :score => 4, :some_key => 'value'},{:name => "Baba", :score => 5, :some_key => 'value'}] 
p input.uniq { |e| e[:name] } 

выше решение работает для рубина> 1.9, для более ранних версий рубина вы могли бы использовать что-то вдоль этих линий:

input = [{:name => "Kutty", :score => 2, :some_key => 'value'},{:name => "Kutty", :score => 4, :some_key => 'value'},{:name => "Baba", :score => 5, :some_key => 'value'}] 
unames = [] 
new_input = input.delete_if { |e| 
    if unames.include?(e[:name]) 
    true 
    else 
    unames << e[:name] 
    false 
    end 
} 
p new_input 
+0

Не работает. Я получаю тот же результат. Я использую ruby ​​1.8.7. В любом случае это помогает мне. – Jak

3

Попробуйте это решение ..

input = [{:name => "Kutty", :score => 2, :some_key => 'value'}, 
     {:name => "Kutty", :score => 4, :some_key => 'value'}, 
     {:name => "Baba", :score => 5, :some_key => 'value'}] 


a = [] 
output = [] 
input.collect do |i| 
    input.delete(i) if !a.include?(i[:name]) 
    output << i if !a.include?(i[:name]) 
    a << i[:name] if !a.include?(i[:name]) 
end 


output = [{:some_key=>"value", :name=>"Kutty", :score=>2}, 
      {:some_key=>"value", :name=>"Baba", :score=>5}] 

ОБНОВЛЕНО

output = {} 
input.each do |e| 
    ref = output[e[:name]] 
    if ref && ref[:score] > e[:score] 
    #nothing 
    else 
    output[e[:name]] = e 
    end 
end 

проверка выход:

puts output.values 
+0

Спасибо Sangeeth .. ваше решение работает нормально, но я жду больше ответов. так как мне нужен лучший подход. – Jak

+0

Спасибо Арун .. Я обновил ответ, пожалуйста, проверьте его. – sangeethkumar

+0

Это гораздо лучший подход. благодаря – Jak

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