Для скорости я бы сделал следующее, для чего требуется только один проход через каждый из двух массивов.Этот метод сохраняет порядок.Сначала я представлю код, который не изменяет исходный массив, а затем покажу, как его можно легко изменить, чтобы изменить.
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 }