删除Ruby数组中的冗余或重复元组
想象一下下面的Ruby数组:
[9, 9, 5, 5, 5, 2, 9, 9]
删除多余元组的最简单方法是什么,产生如下输出:
[9, 5, 2, 9]
uniq
不正确,因为它正在检查整个数组。 输入的顺序很重要,必须保留。 对此有直接的解决方法吗?
谢谢!
我会使用Enumerable#chunk
2.0.0-p0 :001 > a = [9, 9, 5, 5, 5, 2, 9, 9] => [9, 9, 5, 5, 5, 2, 9, 9] 2.0.0-p0 :002 > a.chunk { |e| e }.map(&:first) => [9, 5, 2, 9]
我会这样做的
b = []; a.each { |n| b << n if b.last != n }
和b
是结果
只需要一次arrays扫描
我最喜欢Arup的答案,但是如果你想要一个与没有chunk
版本兼容的方法,你可以做
a = [9, 9, 5, 5, 5, 2, 9, 9] a.inject([a[0]]) { |b,c| b.last == c ? b : b << c } # => [9, 5, 2, 9]
这是我的版本:
a.each_with_object([]) { |el, arr| arr << el if arr.last != el } #=> [9, 5, 2, 9]
对于那些希望删除“冗余”值的问题,OP试图删除“重复连续”值,而不是“冗余”或“重复”值并使用错误的单词。 他们是不同的情况。
为了澄清,删除多余或重复的值将是:
asdf = [9, 9, 5, 5, 5, 2, 9, 9] asdf.uniq # => [9, 5, 2]
要么:
asdf & asdf # => [9, 5, 2]
要么:
require 'set' asdf.to_set.to_a # => [9, 5, 2]
而且,是的,我知道OP正在要求不同的结果。 这是为了显示所提问题的答案,而不是满足所需输出的答案。 为此,请参阅所选答案。
这是为了展示如何使用Enumerator#next和Enumerator#peek方法直接使用枚举器。
def purge_conseq_dups(arr) return arr if arr.empty? enum = arr.to_enum a = [] loop do e = enum.next a << e unless e == enum.peek end a << arr.last end asdf = [9, 9, 5, 5, 5, 2, 9, 9] purge_conseq_dups(asdf) #=> [9, 5, 2, 9]
- 当
e
是枚举器enum
的最后一个元素时,enum.peek
引发一个StopInteration
exception,它由Kernel#loop挽救,它通过断开循环来响应。 此时剩下的就是将arr
的最后一个元素追加到a
。 - 我们可以写
a << e
而不是a << arr.last
,只要我们在循环之前初始化e
(例如,e = nil
),这样变量将在最后一行的范围内。