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] }
任何人都可以提出不那么丑陋的东西吗?
答案 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
但它或多或少相同。