Удалить элементы массива по индексам не деструктивно - PullRequest
1 голос
/ 25 февраля 2020

Допустим, у вас есть что-то вроде этого:

my_array = ['some_rather', 'long_named', 'array_element', 'entry']

Я хочу удалить произвольные записи по индексу из my_array, не меняя его, и я хочу, чтобы отфильтрованный (то есть массив с удаленными индексами) был возвращен из моего вызов. Кроме того, я хочу избежать цепочки 4 отдельных вызовов и написать блок, делая это.

Пример:

filtered_array = my_array.drop_indices(1,3)

Ответы [ 3 ]

2 голосов
/ 25 февраля 2020

Вы можете связать Enumerable with_index с методом Array reject, чтобы сделать то, что вы хотите, хотя это может нарушить ваше желание не связывать отдельные вызовы метода или писать блок чтобы сделать это:

my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]

filtered = my_array.reject.with_index { |_, index| indices_to_remove.include?(index) }

p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]

Если это не приемлемо, единственное, о чем я могу подумать сейчас - сохранить дубликаты (как отмечено в моем комментарии к вашему решению), это изменить с indices_to_remove до indices_to_keep:

my_array = ['some_rather', 'long_named', 'array_element', 'entry', 'long_named']
indices_to_remove = [1, 3]
indices_to_keep = [*(0...my_array.length)] - indices_to_remove

filtered = my_array.values_at(*indices_to_keep)
p filtered # => ["some_rather", "array_element", "long_named"]
p my_array # => ["some_rather", "long_named", "array_element", "entry", "long_named"]
0 голосов
/ 26 февраля 2020

Еще одно возможное решение с некоторым дополнением, теперь оно также будет работать с отрицательными индексами:

array = %w( a b c d e f )
indexes = [1, 2, -1, -9, -6, 6]

def array_except(array, *indexes)
  indexes = indexes.map { |e| e.negative? ? e + array.length : e }
  array.values_at(*((0...array.length).to_a - indexes))
end

array_except(array, *indexes)
=> ["d", "e"]
array_except(array, 0, -1)
=> ["b", "c", "d", "e"]
0 голосов
/ 25 февраля 2020

Для массивов с дублированными элементами лучшее, что я знаю:

array = [0,15,8,15,8]
indices_to_remove = [1,4]
res = array.reject.with_index{ |_,i| indices_to_remove.include?(i) }

возвращает

[0,8,15]

Дополнительно для массивов с уникальными такие записи, как набор пользователей

(используя определения переменных из вопроса)

filtered_array = my_array - my_array.values_at(1,3)

Бонус, если ваши индексы находятся внутри самого массива:

indices_to_remove = [1,3]
filtered_array = my_array - my_array.values_at(*indices_to_remove)

Я думаю, что это довольно наглядно, не неудобно и не короче, чем нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...