【问题标题】:Eliminate consecutive duplicates of list elements消除列表元素的连续重复
【发布时间】:2011-04-04 21:43:10
【问题描述】:

消除列表元素连续重复的最佳解决方案是什么?

list = compress(['a','a','a','a','b','c','c','a','a','d','e','e','e','e']).
p list # => # ['a','b','c','a','d','e']

我有这个:

def compress(list)
  list.map.with_index do |element, index| 
    element unless element.equal? list[index+1]
  end.compact
end

Ruby 1.9.2

【问题讨论】:

标签: ruby


【解决方案1】:

使用Enumerable#chunk 的好机会,只要您的列表不包含nil

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

对于早于 2.2.x 的 Ruby,您可以使用 require "backports/2.2.0/kernel/itself" 或使用 {|x| x} 代替 (&:itself)

对于早于 1.9.2 的 Ruby,您可以require "backports/1.9.2/enumerable/chunk" 获取它的纯 Ruby 版本。

【讨论】:

  • 有一天我会摆脱我的懒惰,为 Identity = ->x { x } 写一个 REP 以包含在核心库中。
  • @Jörg: 还是Object#self?然后可以写&:self。不过,在这两种情况下,我们都不会获得太多的打字……
  • @JörgWMittag:对于self/identity/?,请参阅bugs.ruby-lang.org/issues/6373
  • @Marc-AndréLafortune:同样可以使用itselflist.chunk(&:itself).map(&:first) 来实现
  • @potashin 不会回到 2011 年!
【解决方案2】:

这样做(前提是每个元素都是单个字符)

list.join.squeeze.split('')

【讨论】:

    【解决方案3】:

    Ruby 1.9+

    list.select.with_index{|e,i| e != list[i+1]}
    

    关于@sawa,谁告诉我with_index :)

    正如@Marc-André Lafortune 注意到的,如果您的列表末尾有nil,它对您不起作用。我们可以用这个丑陋的结构来修复它

    list.select.with_index{|e,i| i < (list.size-1) and e != list[i+1]}
    

    【讨论】:

    • 你正在使用它! (通过数组你的意思是列表。)好主意。
    • 您会发现这个案例非常适合我的老问题。以这种方式使用 iterator 会很好:list.select{ |item| item != item.next }
    • @fl00r 对于您之前的问题,我明白了,这很好。 (顺便说一下,list.size --> list.size - 1,或者你想改用&lt;?)你的答案还是很简单的。
    【解决方案4】:
    # Requires Ruby 1.8.7+ due to Object#tap
    def compress(items)
      last = nil
      [].tap do |result|
        items.each{ |o| result << o unless last==o; last=o }
      end
    end
    list = compress(%w[ a a a a b c c a a d e e e e ])
    p list
    #=> ["a", "b", "c", "a", "d", "e"]
    

    【讨论】:

    • 这是我可以使用哈希数组的唯一答案
    【解决方案5】:
    arr = ['a','a','a','a','b','c','c','a','a','d','e','e','e','e']
    
    enum = arr.each
      #=> #<Enumerator: ["a", "a", "a", "a", "b", "c", "c", "a", "a", "d",
      #                  "e", "e", "e", "e"]:each>
    a = []
    loop do
      n = enum.next
      a << n unless n == enum.peek
    end
    a #=> ["a", "b", "c", "a", "d"]
    

    Enumerator#peek 在已经返回枚举数的最后一个元素时引发StopIteration 异常。 Kernel#loop 通过跳出循环来处理该异常。

    Array#eachEnumerator#nextKernel#to_enum1 可以用来代替Array#each

    1 to_enumObject 实例方法,在Kernel 模块中定义,但在Object 类中记录。明白了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 2020-01-25
      • 2020-12-24
      • 2011-08-09
      • 1970-01-01
      • 2011-11-30
      相关资源
      最近更新 更多