我在 Ruby 1.9.3 中有一个包含这样的字符串的变量
#HELLO
#HELLO
#HELLO
#HELLO
#WORLD
#WORLD
#WORLD
#WORLD
#FOO
#BAR
#WORLD
我希望它被转换成类似的东西:
4 times #HELLO end
4 times #WORLD end
#FOO
#BAR
#WORLD
也就是说,我希望将连续的重复字符串组合为一个,并将数量放在一边。
有没有使用 Ruby 的函数式编程能力或其他技术的巧妙方法?
如果你在一个类似 unix 的盒子上,你可能可以通过uniq -c
. 之后您可能需要稍微清理一下输出sed
,但这应该相对简单。
但是我确信也有一个整洁的纯红宝石解决方案。
试试这个:
str = "#HELLO
#HELLO
#HELLO
#HELLO
#WORLD
#WORLD
#WORLD
#WORLD
#FOO
#BAR
#WORLD"
result = ""
identical_lines = 1
str << "\n " # we need a last line to compare
str.lines.each_cons(2) do |line1,line2|
if line1 == line2
identical_lines += 1
elsif identical_lines > 1
result << "#{identical_lines} times #{line1.chomp} end\n"
identical_lines = 1
else
result << line1
end
end
puts result
该程序输出
4 times #HELLO end
4 times #WORLD end
#FOO
#BAR
#WORLD
像这样的东西:
text.each_line.each_with_object(Hash.new(0)).do |e,h|
h[e.chomp] += 1
end.each.map do |k,v|
v > 1 ? "#{v} times #{k} end" : k
end.tap do |array|
File.open(...) { |f| array.each { |e| f.puts e } }
end
如果涉及大量,您应该使用压缩,不要重新发明轮子,而只是为了好玩:
s = %q{#HELLO
#HELLO
#HELLO
#HELLO
#WORLD
#WORLD
#WORLD
#WORLD
#FOO
#BAR
#WORLD}
s.split.inject([[]]) { |m, s| !s.empty? && (m[-1][0] != s) ? (m << [s,1]) : m[-1][1] += 1;m }.drop 1
#=>[["#HELLO", 4], ["#WORLD", 4], ["#FOO", 1], ["#BAR", 1], ["#WORLD", 1]]
我首先将字符串拆分为一个数组,然后在该数组上进行折叠(注入),消除连续的双打并将结果放入二维数组中