ruby - 为什么这个 while 循环内外的变量这个词不同?

标签 ruby loops recursion scope

运行以下代码时,我得到了令人惊讶的输出。为什么第三次调用递归函数时,word变量的值在进入while循环前后发生变化?

def get_perms(word)
  perms = []
  get_perm_recursive("",word, perms)
  perms
end

def get_perm_recursive(prefix, word, perms)
  puts "---------------------"
  if word.length == 0
    perms << prefix
  end

  i = 0
  puts "Word outside loop: #{word}"
  while i < word.length
    puts "Word inside loop: #{word}"
    prefix << word[i]
    new_word = word[0...i] + word[i+1..-1]
    get_perm_recursive(prefix, new_word, perms)
    i += 1
  end

end

 get_perms("ab")

输出:

---------------------
Word outside loop: ab
Word inside loop: ab
---------------------
Word outside loop: b
Word inside loop: b
---------------------
Word outside loop: 
Word inside loop: ab
---------------------
Word outside loop: a
Word inside loop: a
---------------------
Word outside loop: 

最佳答案

不是。您误解了生成输出的迭代。

---------------------  # this is iteration 1
Word outside loop: ab # this is iteration 1
Word inside loop: ab # this is iteration 1
--------------------- # this is iteration 2
Word outside loop: b # this is iteration 2
Word inside loop: b # this is iteration 2
--------------------- # this is iteration 3
Word outside loop: # this is iteration 3
# Iteration 3 has NO FURTHER OUTPUT (because i is not less than word.length)
# we are returned to Iteration 2
# but... Iteration 2 ALSO has NO FURTHER OUTPUT (because i in that iteration, increased to 1, is not less than word length)
# we are returned to Iteration 1
Word inside loop: ab # this is the SECOND while loop in the first iteration, so yes, the word is "ab"

这里有一个简单的方法来修改输出以查看您正在进行的迭代...第一次迭代有一个 iteration 参数,默认为 1,并且递增对于下一次迭代的每次调用:

def get_perm_recursive(prefix, word, perms, iteration=1)
  puts "---------------------"
  if word.length == 0
    perms << prefix
  end

  i = 0
  puts "Word outside loop: #{word} in iteration: #{iteration}"
  while i < word.length
    puts "Word inside loop: #{word} in iteration: #{iteration}""
    prefix << word[i]
    new_word = word[0...i] + word[i+1..-1]
    get_perm_recursive(prefix, new_word, perms, iteration + 1)
    i += 1
  end

end

顺便说一下...您似乎期望 get_perms 返回一组权限(排列?)。但是您没有机制返回在排列调用中计算的 perms。您需要确保每个方法都返回 perms 并且您需要将返回的 perms 分配给一个变量。

将第一种方法改为...

def get_perms(word)
  perms = []
  perms = get_perm_recursive("",word, perms)
  perms
end

...以便将 get_perm_recursive 的结果分配给一个变量,或者甚至更好,将 get_perm_recursive 作为最后执行的语句。

def get_perms(word)
  get_perm_recursive("",word, [])
end

您还需要将 get_perm_recursive 的输出捕获在 get_perm_recursive 中,所以替换,

get_perm_recursive(prefix, new_word, perms)

perms = perms + get_perm_recursive(prefix, new_word, perms)

get_perm_recursive 方法的最后一条语句应该返回 perms 数组...

    i += 1
  end
  perms

end

我要提到的另一件事,结构

i = 0 
while i < limiting_value
  ...
  i += 1
end

...不是 ruby 风格的。一个更典型和更好的实现是

(0...limiting_value) do |i| 
  ...
end

关于ruby - 为什么这个 while 循环内外的变量这个词不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40064481/

相关文章:

javascript - 如何在深度未知的数组内递归构建子数组的路径

ruby - 在 Sinatra 应用程序中获取 Rack 安装路径

ruby - 用于 Ruby 的 HBase ORM

java - 使用用户输入的数字退出循环

sql - 将平面表解析为树的最有效/优雅的方法是什么?

haskell - 递归函数组合中的惰性

ruby - Cygwin 工具与 Linux 终端有何不同? Cygwin 是否有任何缓慢问题

ruby - Rails 4 before_action,将参数传递给调用的方法

c# - 在 C# 中重叠

python - 在Python中迭代嵌套元组