为什么单词变量在while循环内外都不同?

时间:2016-10-15 21:38:05

标签: 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: 

2 个答案:

答案 0 :(得分:1)

不是。你错误地解释了产生输出的迭代。

---------------------  # 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并且您需要将返回的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 WITHIN 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

......不是红宝石般的。更典型,更好的实现是

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

答案 1 :(得分:0)

你有一个带有循环的递归函数。尝试添加一些额外的日志记录:

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

def get_perm_recursive(prefix, word, perms)
  $level += 1
  puts "level: #{$level}"
  puts "entering get_perm_recursive(#{prefix},#{word},#{perms}"
  if word.length == 0
    perms << prefix
  end

  i = 0
  puts "Word outside loop: #{word}"
  while i < word.length
    puts "Word inside loop: #{word}, #{i}"
    prefix << word[i]
    new_word = word[0...i] + word[i+1..-1]
    puts "Calling gets_perm_recursive recursively"
    get_perm_recursive(prefix, new_word, perms)
    i += 1
  end
  puts "done with gets perm recursive #{$level}"

  $level -= 1
end

get_perms("ab")

输出:

level: 1
entering get_perm_recursive(,ab,[]
Word outside loop: ab
Word inside loop: ab, 0
Calling gets_perm_recursive recursively
level: 2
entering get_perm_recursive(a,b,[]
Word outside loop: b
Word inside loop: b, 0
Calling gets_perm_recursive recursively
level: 3
entering get_perm_recursive(ab,,[]
Word outside loop:
done with gets perm recursive 3
done with gets perm recursive 2
Word inside loop: ab, 1
Calling gets_perm_recursive recursively
level: 2
entering get_perm_recursive(abb,a,["abb"]
Word outside loop: a
Word inside loop: a, 0
Calling gets_perm_recursive recursively
level: 3
entering get_perm_recursive(abba,,["abba"]
Word outside loop:
done with gets perm recursive 3
done with gets perm recursive 2
done with gets perm recursive 1