繁体   English   中英

如何提高这个小Ruby function的性能?

[英]How can I improve the performance of this small Ruby function?

我目前正在执行 Ruby 质询,并且对于某些字符串输入很长(10.000+ 个字符)的测试用例, Terminated due to timeout出现错误。

如何改进我的代码?

Ruby 挑战说明

给您一个仅包含字符 A 和 B 的字符串。 您的任务是将其更改为没有匹配的相邻字符的字符串。 为此,您可以删除字符串中的零个或多个字符。

您的任务是找到所需删除的最少数量。

例如,给定字符串s = AABAAB ,删除位置03A以使s = ABAB删除2

我的 function

def alternatingCharacters(s)
    counter = 0
    s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }
    return counter
end

谢谢!

这可能会更快地返回计数:

str.size - str.chars.chunk_while{ |a, b| a == b }.to_a.size

第二部分将String#chars方法与Enumerable#chunk_while结合使用。 这样第二部分在子数组中分组:

'aababbabbaab'.chars.chunk_while{ |a, b| a == b}.to_a
#=> [["a", "a"], ["b"], ["a"], ["b", "b"], ["a"], ["b", "b"], ["a", "a"], ["b"]]

如果可以使用,则squeeze

str.length - str.squeeze.length

否则,您可以尝试匹配前面有另一个A (或B )的那些A (或B )的正则表达式:

str.enum_for(:scan, /(?<=A)A|(?<=B)B/).count

使用enum_for可以避免创建中间数组。

主要问题:

 s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }

是您不将chars保存到变量中的事实。 s.chars会将字符串撕成一个字符数组。 循环外的第一个s.chars调用很好。 但是,没有理由对s中的每个字符都这样做。 这意味着如果您有一个 10.000 个字符的字符串,您将实例化大小为 10.000 的 10.001 arrays。

重新使用字符数组会给你带来巨大的性能提升:

require 'benchmark'

s  = ''
options = %w[A B]
10_000.times { s << options.sample }
Benchmark.bm do |x|
  x.report do
    counter = 0
    s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }
    #           create a character array for each iteration ^
  end

  x.report do
    counter = 0
    chars = s.chars # <- only create a character array once
    chars.each_with_index { |char, idx| counter += 1 if chars[idx + 1] == char }
  end
end
       user     system      total        real
   8.279767   0.000001   8.279768 (  8.279655)
   0.002188   0.000003   0.002191 (  0.002191)

您还可以使用each_conscount之类的枚举器方法来简化代码,这不会大大增加性能成本,但会使代码更具可读性。

Benchmark.bm do |x|
  x.report do
    counter = 0
    chars = s.chars
    chars.each_with_index { |char, idx| counter += 1 if chars[idx + 1] == char }
  end

  x.report do
    s.each_char.each_cons(2).count { |a, b| a == b }
    #  ^ using each_char instead of chars to avoid
    #    instantiating a character array
  end
end
       user     system      total        real
   0.002923   0.000000   0.002923 (  0.002920)
   0.003995   0.000000   0.003995 (  0.003994)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM