2011-01-02 12 views
7

trzeba połączyć kolejno powtarzających się elementów w szeregu, tak żeJak scalić kolejne powtarzające się elementy w tablicy?

[1, 2, 2, 3, 1] 

się

[1, 2, 3, 1] 

#uniq nie działa w tym celu. Czemu? Ponieważ #uniq będzie produkować to:

[1, 2, 3] 
+0

dlaczego robi uniq pracować? używasz uniq lub uniq !? – sethvargo

+0

Zobacz także zduplikowane pytanie _ [Wyeliminuj kolejne duplikaty elementów listy] (http://stackoverflow.com/q/5544701/405017) _. – Phrogz

Odpowiedz

7
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] 

ta zwraca nową tablicę jak uniq robi i pracuje w O(n) czasie. Odpowiedź

+0

Poważnie, dobrze zrobione. 'every_cons (2) .select' indeed! – Phrogz

+0

Nie wiedziałem o * each_cons *, nice one! –

-3
+1

-1)) POWIEDZIAŁA w swojej odpowiedzi, że nie działa i 2.) jego uniq! not! uniq – sethvargo

+1

'! uniq' nie jest prawidłową nazwą metody w ruby. 'uniq!' działa tak samo jak 'uniq', ale w miejscu. Tak więc nie jest to, co OP chce (ponieważ chce tylko usunąć * kolejne * duplikaty). – sepp2k

+0

Nie zauważyłem "kolejnego" wymogu duplikatu. OP może chcieć to wyjaśnić. –

3

sepp2k jest już przyjęta, ale oto kilka alternatyw:

# 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 

I chociaż wydajność jest nie wszystko, oto kilka Benchmarki:

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) 

Benchmarki uruchomić na usuwanie duplikatów od orig = (0..1000).map{ rand(5) } 10 000 razy.

10

Jest abstrakcją w rdzeniu, że dość dużo robi pracę, Enumerable#chunk:

xs = [1, 2, 2, 3, 3, 3, 1] 
xs.chunk { |x| x }.map(&:first) 
#=> [1, 2, 3, 1] 
+1

O wiele krótszy, czystszy i wydajniejszy niż przyjęta odpowiedź. – Sim

+1

To nie będzie działać poprawnie, jeśli tablica ma wartości zerowe, ponieważ spowoduje to odrzucenie tych wartości. – Reck

+0

Dobra uwaga. Nie miałem pojęcia, że ​​'chunk' ma te specjalne wartości. Jeśli dane wejściowe mogą mieć te specjalne wartości, wszystkie powinny być zawijane. – tokland

Powiązane problemy