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

时间:2010-03-25 14:29:12

标签: ruby arrays

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

任何人都可以提出不那么丑陋的东西吗?

6 个答案:

答案 0 :(得分:21)

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

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

itself方法是Ruby 2.2+。如果您遇到旧的Ruby或我的backports宝石,请使用{|n| n}。 它是在Ruby 1.9.2中引入的。如果你不幸使用旧的红宝石,你可以使用我的backports gem和require 'backports/1.9.2/enumerable/chunk'

答案 1 :(得分:5)

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

答案 2 :(得分:1)

除非你非常关注该块计算的速度,否则我建议您只需将此行添加到块的末尾即可获得所需的输出:

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!电话即可进行排序。

答案 3 :(得分:1)

另一种解决方案:

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}

答案 4 :(得分:1)

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

答案 5 :(得分:0)

我只能想到这个

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

但它或多或少相同。