删除Ruby数组中相邻的相同元素?

Ruby 1.8.6

我有一个包含数值的数组。 我想减少它,使得相同值的序列减少到该值的单个实例。

所以我想要

a = [1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3] 

减少到

 [1, 2, 3, 2, 3] 

如您所见, Array#uniq在这种情况下不起作用。

我有以下,有效:

 (a.size - 1).downto(1) { |i| a[i] = nil if a[i - 1] == a[i] } 

任何人都可以想出一些不那么难看的东西吗?

对于最简单,最精简的解决方案,您可以使用Enumerable#chunk方法:

 a.chunk{|n| n}.map(&:first) 

它是在Ruby 1.9.2中引入的。 如果你不幸使用旧的ruby,你可以使用我的backports gem并require 'backports/1.9.2/enumerable/chunk'

 a.inject([]){|acc,i| acc.last == i ? acc : acc << i } 

除非你非常关心块计算的速度,否则我建议你只需将这一行添加到块的末尾以获得所需的输出:

 a.compact! 

这将删除你之前引入数组的所有nil元素(可能是重复的),形成你想要的输出: [1, 2, 3, 2, 3]

如果你想要另一种算法,这里有一些比你更难的东西。 🙂

 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 

给你输出:

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

在我看来,你的代码很好。 只需添加a.compact! 打电话,你排序。

另一种方案:

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

要么

 a.each_cons(2).inject([a[0]]) {|acc, (x,y)| x == y ? acc : acc << y} 

如果数字都是单个数字0-9: a.join.squeeze('0-9').each_char.to_a应该有效。

我只能想到这一点

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

但它或多或少相同。