簡體   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