#ruby
#ruby
Вопрос:
У меня есть рабочий код, но он мне не нравится, он мне очень не нравится. У меня есть две разные коллекции, и я хочу удалить элементы, которые имеют совпадающие ключи, из одной коллекции. Я «выбрал» то, что пользователь выбрал из «вариантов». Итак, я хочу отображать только «варианты», которые еще не выбраны. Вот код:
@picked.each do |p|
i = 0
@choices.each do |c|
if p.choices_id == c.id
@choices.delete_at(i)
break
end
i = 1
end
end
завершение
Мне особенно не нравится переменная «i». Просто подумал, что я посмотрю, что другие могут с этим сделать.
Комментарии:
1. Что такое
choices_id
?Object#id
изношен. Вместо этого вам следует использоватьObject#object_id
.
Ответ №1:
@choices.reject! { |c| @picked.index { |p| p.choices_id == c.id } }
Комментарии:
1. Вау! Действительно лаконично! Спасибо.
Ответ №2:
each_with_index и с_index для Ruby 1.9
И улучшения для вашего кода
choices_ids = @picked.map(amp;:choices_id)
@choices.delete_if{ |c| choices_ids.include? c.id }
api: delete_if
UPD
Также вы всегда можете просто вызвать это:
@choices - @picked.map(amp;:choices).flatten
или
@choices -= @picked.map(amp;:choices).flatten
Комментарии:
1. Ха, не видел, чтобы «amp;» использовалось раньше, и даже не знаю, что это значит, так что есть чему поучиться, большое спасибо!
Ответ №3:
Ruby поддерживает пересечение и различие для наборов:
picked = %w[1 2 3]
choices = %w[1 2 3 4 5]
choices - picked # => ["4", "5"]
Редактировать:
class Pick
attr_reader :choices_id
def initialize(id)
@choices_id = id
end
end
class Choice
attr_reader :id
def initialize(id)
@id = id
end
end
# cobble up some collections of objects
picked = %w[1 2 3].map{ |p| Pick.new(p) }
choices = %w[ 1 2 3 4 5].map{ |c| Choice.new(c) }
choices.map{ |c| c.id } - picked.map{ |p| p.choices_id } # => ["4", "5"]
Комментарии:
1. Я бы использовал это, но оба были коллекциями объектов, которые были разными. Спасибо. Не могу дождаться, когда я действительно смогу использовать что-то подобное в производственном коде, потому что это то немногое, что я знаю о Ruby!
2. ОК. Думаю, мне придется объяснить это немного подробнее.