考虑以下数组:
x = ['a', 'b', 'b', 'c', 'a', 'a', 'a']
我希望得到一个显示每个元素按顺序重复次数的结果。因此,最终可能会得到以下内容:
[['a', 1], ['b', 2], ['c', 1], ['a', 3]]
结果的结构并不是那么重要...如果需要,可能还有其他的数据类型。
考虑以下数组:
x = ['a', 'b', 'b', 'c', 'a', 'a', 'a']
我希望得到一个显示每个元素按顺序重复次数的结果。因此,最终可能会得到以下内容:
[['a', 1], ['b', 2], ['c', 1], ['a', 3]]
结果的结构并不是那么重要...如果需要,可能还有其他的数据类型。
为此目的,1.9 版本引入了 Enumerable#chunk
方法:
x.chunk{|y| y}.map{|y, ys| [y, ys.length]}
chunk
的目的是否是这样。 - Swanand[(y, len(list(ys))) for (y, ys) in itertools.groupby(x)]
。 - tokland这不是一个通用的解决方案,但如果你只需要匹配单个字符,可以像这样完成:
x.join.scan(/(\w)(\1*)/).map{|x| [x[0], x.join.length]}
Enumerable#Chunk
在你的例子中也可以使用。请查看下面pguardiario的答案。 - Swanand这是一行解决方案。逻辑与Matt建议的相同,尽管在x前面使用nil也可以正常工作:
x.each_with_object([]) { |e, r| r[-1] && r[-1][0] == e ? r[-1][-1] +=1 : r << [e, 1] }
Array
或 Enumerable
方法(除了 #chunk
)。但归根结底,这段代码简单、易读且有效。我们并不总是有扫描 ruby-doc 的特权,但当我们拥有时,就像重构我这样的代码 :) - bloudermilk这是我的方法:
# Starting array
arr = [nil, nil, "a", "b", "b", "c", "a", "a", "a"]
# Array to hold final values as requested
counts = []
# Array of previous `count` element
previous = nil
arr.each do |letter|
# If this letter matches the last one we checked, increment count
if previous and previous[0] == letter
previous[1] += 1
# Otherwise push a new array for letter/count
else
previous = [letter, 1]
counts.push previous
end
end
我应该指出,这不会遭受Matt Sanders所描述的同样问题,因为我们在迭代的第一次时就非常注意。
fold
实现的函数http://en.m.wikipedia.org/wiki/Fold_(higher-order_function))。 - John Bachir