Как объединить последовательные повторяющиеся элементы в массиве? - PullRequest
7 голосов
/ 02 января 2011

Мне нужно объединить последовательно повторяющиеся элементы в массиве, так что

[1, 2, 2, 3, 1]

становится

[1, 2, 3, 1]

#uniq не работает для этой цели.Зачем?Потому что #uniq будет производить это:

[1, 2, 3]

Ответы [ 4 ]

10 голосов
/ 12 ноября 2011

В ядре есть абстракция, которая в значительной степени выполняет свою работу, Enumerable # chunk :

xs = [1, 2, 2, 3, 3, 3, 1]
xs.chunk { |x| x }.map(&:first)
#=> [1, 2, 3, 1]
7 голосов
/ 02 января 2011
def remove_consecutive_duplicates(xs)
  [xs.first] + xs.each_cons(2).select do |x,y|
    x != y
  end.map(&:last)
end

remove_consecutive_duplicates([1, 2, 2, 3, 1])
#=> [1,2,3,1]

Возвращает новый массив, как uniq делает и работает за O(n) время.

3 голосов
/ 02 января 2011

Ответ sepp2k уже принят, но есть несколько альтернатив:

# Because I love me some monkeypatching
class Array
  def remove_consecutive_duplicates_2
    # Because no solution is complete without inject
    inject([]){ |r,o| r << o unless r.last==o; r }
  end

  def remove_consecutive_duplicates_3
    # O(2n)
    map.with_index{ |o,i| o if i==0 || self[i-1]!=o }.compact
  end

  def remove_consecutive_duplicates_4
    # Truly O(n)
    result = []
    last   = nil
    each do |o|
      result << o unless last==o
      last = o
    end
    result
  end
end

И хотя производительность не все, вот некоторые тесты:

Rehearsal --------------------------------------------
sepp2k     2.740000   0.010000   2.750000 (  2.734665)
Phrogz_2   1.410000   0.000000   1.410000 (  1.420978)
Phrogz_3   1.520000   0.020000   1.540000 (  1.533197)
Phrogz_4   1.000000   0.000000   1.000000 (  0.997460)
----------------------------------- total: 6.700000sec

               user     system      total        real
sepp2k     2.780000   0.000000   2.780000 (  2.782354)
Phrogz_2   1.450000   0.000000   1.450000 (  1.440868)
Phrogz_3   1.530000   0.020000   1.550000 (  1.539190)
Phrogz_4   1.020000   0.000000   1.020000 (  1.025331)

Тесты запускаются при удалении дубликатов из orig = (0..1000).map{ rand(5) } 10000 раз.

0 голосов
/ 02 января 2011

не !uniq не работает для того, что вы делаете?

http://ruby -doc.org / документы / ProgrammingRuby / html / ref_c_array.html

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