Ruby 中的嵌套循环

Nested loops in Ruby

我正在尝试计算 Ruby 中字符串的相似前缀开头的数量。例如;输入 "ababaa" 应该输出 11;

ababaa = 6
 babaa = 0
  abaa = 3
   baa = 0
    aa = 1
     a = 1

我已经得到了下面的代码,使用嵌套循环将上面的每一个都作为一个数组进行遍历,但是看起来 Ruby 目前正在输出第一个数组的计数对象,"ababaa".

Solved, thanks :)

def string_suffix(string)
num = 0
ary = []
string.length.times do
  ary << string[num..string.length]
  num = num + 1
end
result = 0
ary.each do |x| # ["ababaa", "babaa", "abaa", "baa", "aa", "a"] 
  x.chars.each_with_index do |c,index|
    break unless c == string[index]
      result = result + 1
  end
end
return result
end

我已经看了很远,仍然无法解决问题,看起来(最终的,嵌套的)数组在 'ary' 数组的第一次迭代后被打破,只是返回那个输出。

您仍在循环中时返回结果。您需要将 result = 0 移出循环,并将 return result 语句也移出循环。目前函数正在经历循环的第一次迭代("ababaa",所有字符都匹配),但您希望结果等于所有结果的总和。

此外,而不是做:

count = 0
x.chars.each do |x|
    if x == string[count]
        count = count + 1
        result = result + 1
    else
        count = count + 1
    end
end

您可以使用函数 each_with_index,得到

x.chars.each_with_index do |c,index|
    if c == string[index]
        result = result + 1
    end
end

但是,由于您要计算子字符串中有多少个字符是字符串的前缀,因此您希望在第一次找到不等于字符串 [index] 的字符 c 时中断,这样您就不会' 最终计算额外的字符。然后循环变为:

x.chars.each_with_index do |c,index|
    if c == string[index]
        result = result + 1
    else
        break
    end
end

我注意到您在第二个循环的最后 return 计算结果。这意味着在您完成数组中的第一项之后,函数 returns 只是第一项的结果。将您的 return 语句移到循环外。

据我了解,问题是这样的:给定一个字符串 s,对于每个 i = 0..s.size-1,计算 s[0..-i-1] 中与相应字符匹配的前导字符数(即,在相同的偏移量下)s[i..-1],并对这些 s.size 小计求和。

这是一个类似于 Ruby 的方法,使用 Enumerable#reduce (aka inject) and Enumerable#take_while:

str = "ababaa"

arr = str.chars
(0...arr.size).reduce(0) do |tot,i|
  tot + arr[0..-i-1].zip(arr[i..-1]).take_while { |x,y| x == y }.size
end
  #=> 11

步骤:

arr = str.chars
  #=> ["a", "b", "a", "b", "a", "a"] 
r = 0...arr.size
  #=> 0...6 

r的第一个元素传递给块时,块变量设置为:

tot = 0
i   = 0

因此块计算如下:

a = arr[0..-i-1].zip(arr[i..-1])
  #=> arr[0..-1].zip(arr[0..-1])
  #=> arr.zip(arr)
  #=> ["a", "b", "a", "b", "a", "a"].zip(["a", "b", "a", "b", "a", "a"])
  #=> [["a", "a"], ["b", "b"], ["a", "a"], ["b", "b"], ["a", "a"], ["a", "a"]]

b = a.take_while { |x,y| x == y }
  #=> [["a", "a"], ["b", "b"], ["a", "a"], ["b", "b"], ["a", "a"], ["a", "a"]]

tot + b.size
  #=> 0 + 6
  #=> 6

请注意,对于传递给块的 arr 的第一个元素,此计算将始终等于 arr.size

arr 的下一个元素传递给块时,块变量 i 被设置为 1。我们刚刚计算的 tot 等于 6。因此,块计算是:

a = arr[0..-i-1].zip(arr[i..-1])
  #=> arr[0..-2].zip(arr[1..-1])
  #=> ["a", "b", "a", "b", "a"].zip(["b", "a", "b", "a", "a"])
  #=> [["a", "b"], ["b", "a"], ["a", "b"], ["b", "a"], ["a", "a"]] 

b = a.take_while { |x,y| x == y }
  #=> [] 
tot + b.size
  #=> 6 + 0
  #=> 6

其余计算类似。在 arr 的所有元素都被发送到区块后, reduce returns tot.

的值