Подтвердить что ты не робот

Удалить соседние идентичные элементы в Ruby Array?

Ruby 1.8.6

У меня есть массив, содержащий числовые значения. Я хочу уменьшить его, чтобы последовательности одного и того же значения были сведены к одному экземпляру этого значения.

Итак, я хочу

a = [1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3]

чтобы уменьшить до

[1, 2, 3, 2, 3]

Как вы можете видеть, Array#uniq в этом случае не будет работать.

У меня есть следующее, которое работает:

(a.size - 1).downto(1) { |i| a[i] = nil if a[i - 1] == a[i] }

Может ли кто-нибудь придумать что-то менее уродливое?

4b9b3361

Ответ 1

Для самого простого и легкого решения вы можете использовать метод Enumerable#chunk:

a.chunk(&:itself).map(&:first)

itself метод - Ruby 2. 2+. Используйте {|n| n} {|n| n} если вы застряли в более старом Ruby или в моих backports. Он был введен в Ruby 1.9.2. Если вам не повезло использовать старые рубины, вы можете использовать мой драгоценный камень backports и require 'backports/1.9.2/enumerable/chunk'.

Ответ 2

a.inject([]){|acc,i| acc.last == i ? acc : acc << i }

Ответ 3

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

a.compact!

Это приведет к удалению всех элементов nil, которые вы ранее ввели в массив (возможные дубликаты), формируя желаемый результат: [1, 2, 3, 2, 3]

Если вам нужен другой алгоритм, вот что-то гораздо более уродливое, чем ваше.: -)

require "pp"

a = [1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3]

i = 0

while i < a.size do
  e = a[i]
  j = i

  begin
    j += 1
  end while e == a[j]

  for k in i+1..j-1 do
    a[k] = nil
  end

  i = j
end

pp a
a.compact!
pp a

Выдает результат:

[1, nil, nil, 2, nil, 3, nil, nil, nil, 2, nil, nil, 3, nil, nil]
[1, 2, 3, 2, 3]

По-моему, ваш код в порядке. Просто добавьте вызов a.compact!, и вы отсортированы.

Ответ 4

другое решение:

acc = [a[0]]
a.each_cons(2) {|x,y| acc << y if x != y}

или

a.each_cons(2).inject([a[0]]) {|acc, (x,y)| x == y ? acc : acc << y}

Ответ 5

Если все цифры равны 0-9: a.join.squeeze('0-9').each_char.to_a должны работать.

Ответ 6

Я могу думать только об этом

a.each_with_index{|item,i| a[i] = nil if a[i] == a[i+1] }.compact

но он более или менее одинаковый.