Исключение первого элемента по значению из массива

Я хочу получить что-то вроде этого:

a                       =  [0,1,0,0,1,0,1,0]
a.except(1)           # => [0,0,0,1,0,1,0]
a                     # => [0,1,0,0,1,0,1,0]
a.except(1).except(1) # => [0,0,0,0,1,0]

Как вы видите, первый элемент a, равный аргументу except, удаляется из a.

Я могу сделать:

tmp_a = a.dup
tmp_a.delete_at(a.index(1))
tmp_a

но, на мой взгляд, это похоже на запах. Есть ли более элегантное однострочное решение? (Другими словами - как определить метод "except" для Array?)

UPD

Я решил эту проблему, поэтому

class Array
  def except(elem)
    dup.tap{|a| a.delete_at(a.index(elem))}
  end
end

как вы думаете?

Ответ 1

Что так "взломано" в вашем решении?

Это тоже то, что мне сначала пришло в голову (начал взламывать, прежде чем читать весь вопрос: P)

class Array
  def except(elem)
    tmp = self.dup
    tmp.delete_at(self.index(elem))
    tmp
  end
end

Или вы можете использовать мощность delete_if (включая count Я украл ответ @mudasobwa:

class Array
  def except(elem, count = 1)
    tmp = self.dup
    memo = 0
    tmp.delete_if { |e| elem == e && (memo += 1) <= count }
  end
end

Или вы можете slice ваш массив к битам:

class Array
  def except(elem)
    index = self.index(elem)
    self.slice(0, index) + self.slice(index + 1, self.length)
  end
end

Ответ 2

class Array
  def except what, count = 1
    memo = 0
    map do |e| 
      what == e && (memo += 1) <= count ? nil : e
    end.compact
  end
end

Вышеупомянутое приведет к удалению count входов what:

a.except(1, 2) 
#⇒ [0,0,0,0,1,0]

Ответ 3

Вы можете написать:

a.difference [1]
  #=> [0,0,0,1,0,1,0] 

a #=> [0,1,0,0,1,0,1,0]

где Array#difference определяется в моем ответе здесь.