0

我在 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 的函数式编程能力或其他技术的巧妙方法?

4

4 回答 4

1

如果你在一个类似 unix 的盒子上,你可能可以通过uniq -c. 之后您可能需要稍微清理一下输出sed,但这应该相对简单。

但是我确信也有一个整洁的纯红宝石解决方案。

于 2012-07-03T08:48:52.510 回答
1

试试这个:

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
于 2012-07-03T08:52:38.440 回答
0

像这样的东西:

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
于 2012-07-03T09:02:15.703 回答
0

如果涉及大量,您应该使用压缩,不要重新发明轮子,而只是为了好玩:

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

我首先将字符串拆分为一个数组,然后在该数组上进行折叠(注入),消除连续的双打并将结果放入二维数组中

于 2012-07-03T09:48:17.497 回答