Исключение первого элемента по значению из массива
Я хочу получить что-то вроде этого:
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
определяется в моем ответе здесь.