Удаление элементов из массива Ruby - PullRequest
60 голосов
/ 19 января 2012

Допустим, я пытаюсь удалить элементы из массива a = [1,1,1,2,2,3].Если я выполню следующее:

b = a - [1,3]

Тогда я получу:

b = [2,2]

Однако я хочу, чтобы результат был

b = [1,1,2,2]

, т.е. я только удаляюодин экземпляр каждого элемента в вычтенном векторе не во всех случаях.Есть ли в Ruby простой способ сделать это?

Ответы [ 6 ]

73 голосов
/ 19 января 2012

Вы можете сделать:

a= [1,1,1,2,2,3]
delete_list = [1,3]
delete_list.each do |del|
    a.delete_at(a.index(del))
end

результат: [1, 1, 2, 2]

5 голосов
/ 20 января 2012
[1,3].inject([1,1,1,2,2,3]) do |memo,element|
  memo.tap do |memo|
    i = memo.find_index(e)
    memo.delete_at(i) if i
  end
end
3 голосов
/ 19 января 2012

Не очень просто, но:

a = [1,1,1,2,2,3]
b = a.group_by {|n| n}.each {|k,v| v.pop [1,3].count(k)}.values.flatten
=> [1, 1, 2, 2]

Также обрабатывает случай для кратных в 'вычитаемом':

a = [1,1,1,2,2,3]
b = a.group_by {|n| n}.each {|k,v| v.pop [1,1,3].count(k)}.values.flatten
=> [1, 2, 2]

РЕДАКТИРОВАТЬ: это больше улучшение, сочетающее в себе Norm212 и мой ответчтобы создать «функциональное» решение.

b = [1,1,3].each.with_object( a ) { |del| a.delete_at( a.index( del ) ) }

Поместите его в лямбду, если необходимо:

subtract = lambda do |minuend, subtrahend|
  subtrahend.each.with_object( minuend ) { |del| minuend.delete_at( minuend.index( del ) ) }
end

, затем:

subtract.call a, [1,1,3]
0 голосов
/ 06 января 2019

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

arr = [1,1,1,2,2,3,1]
removals = [1,3,1]

h = removals.group_by(&:itself).transform_values(&:size)
  #=> {1=>2, 3=>1} 
arr.each_with_object([]) { |n,a|
  h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n }
  #=> [1, 2, 2, 1]

arr
  #=> [1, 1, 1, 2, 2, 3, 1] 

Чтобы изменить arr запись:

h = removals.group_by(&:itself).transform_values(&:count)
arr.replace(arr.each_with_object([]) { |n,a|
  h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n })
  #=> [1, 2, 2, 1]

arr
  #=> [1, 2, 2, 1]

Этоиспользует метод 21 st века Hash # transform_values ​​ (новое в MRI v2.4), но вместо этого можно написать:

h = Hash[removals.group_by(&:itself).map { |k,v| [k,v.size] }]

или

h = removals.each_with_object(Hash.new(0)) { | n,h| h[n] += 1 }
0 голосов
/ 03 июля 2018

Простое решение, которое я часто использую:

arr = ['remove me',3,4,2,45]

arr[1..-1]

=> [3,4,2,45]
0 голосов
/ 21 мая 2018
a = [1,1,1,2,2,3]
a.slice!(0) # remove first index
a.slice!(-1) # remove last index
# a = [1,1,2,2] as desired
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...