настройка ruby delete_at

#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. ОК. Думаю, мне придется объяснить это немного подробнее.