Remove adjacent identical elements in a Ruby Array?

前端 未结 6 1549
醉酒成梦
醉酒成梦 2021-02-14 12:55

Ruby 1.8.6

I have an array containing numerical values. I want to reduce it such that sequences of the same value are reduced to a single instance of that value.

相关标签:
6条回答
  • 2021-02-14 13:25

    For the simplest, leanest solution, you could use the method Enumerable#chunk:

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

    The itself method is Ruby 2.2+. Use {|n| n} if you are stuck in an older Ruby, or my backports gems. It was introduced in Ruby 1.9.2. If you're unlucky enough to be using older rubies, you could use my backports gem and require 'backports/1.9.2/enumerable/chunk'.

    0 讨论(0)
  • 2021-02-14 13:28

    If the numbers are all single digits 0-9: a.join.squeeze('0-9').each_char.to_a should work.

    0 讨论(0)
  • 2021-02-14 13:30

    Unless you are very concerned with the speed that block will calculate at, I would suggest you simply add this line to the end of your block to get the desired output:

    a.compact!
    

    That will just remove all the nil elements you introduced to the array earlier (the would-be duplicates), forming your desired output: [1, 2, 3, 2, 3]

    If you want another algorithm, here is something far uglier than yours. :-)

    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
    

    Gives you the output:

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

    In my opinion, your code is fine. Just add the a.compact! call and you are sorted.

    0 讨论(0)
  • 2021-02-14 13:38
    a.inject([]){|acc,i| acc.last == i ? acc : acc << i }
    
    0 讨论(0)
  • 2021-02-14 13:49

    another solution:

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

    or

    a.each_cons(2).inject([a[0]]) {|acc, (x,y)| x == y ? acc : acc << y}
    
    0 讨论(0)
  • 2021-02-14 13:52

    I can think only of this

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

    but it is more or less the same.

    0 讨论(0)
提交回复
热议问题