【问题标题】:How to reset value of local variable within loop?如何在循环中重置局部变量的值?
【发布时间】:2015-11-09 14:36:29
【问题描述】:

我想指出,我已经非常广泛地尝试找到解决方案,我得到的最接近的是this。但是我看不出如何使用map 来解决我的问题。我是 Ruby 的新手,所以请记住这一点。

这是我正在使用的一些代码(简化版):

def base_word input
    input_char_array = input.split('') # split string to array of chars
    @file.split("\n").each do |dict_word|
        input_text = input_char_array
        dict_word.split('').each do |char|
            if input_text.include? char.downcase
                input_text.slice!(input_text.index(char))
            end
        end
    end
end

我需要在每个循环之后将input_text 的值重置回input_char_array 的原始值,但是根据我收集到的信息,因为 Ruby 是基于引用的,我对input_text.slice!(input_text.index(char)) 行所做的修改得到了反映回到原始参考中,结果我很快将input_text 分配给了一个空数组。

如何缓解这种情况?如前所述,我尝试使用.map,但也许我还没有完全理解我应该如何去做。

【问题讨论】:

  • 您期望输出什么?您正在对文本进行切片,但它看起来并没有在任何地方打印或返回。
  • #map 不会解决您问题中的问题,但它可以帮助输出。当您包含有关预期输出的一些信息时,我将使用 #map 更新我的答案。
  • 我没有包含任何内容的原因是因为我真的不相信它是相关的——我的意思是对 input text 进行任何形式的修改都会导致 @ 的原始值987654332@ 也被更改,因此否定了我在“重置”input-text 中试图实现的目标

标签: ruby loops


【解决方案1】:

您可以通过克隆数组来获得独立的引用。显然,这对 RAM 使用有一些影响。

input_text = input_char_array.dup

【讨论】:

  • 在这里使用#slice而不是#slice!会更有意义吗?完全避免#duping?
  • 好吧,那么slice 会做一些复制。
  • 对,只是认为它少了一个方法调用。任何一个都有效;不确定这两种方法是否有明显的好处。
  • 我对此投了赞成票,因为我发现它很有用并且对我的问题有所帮助——如果能看到更多解释/可能的替代方案/含义会很高兴!
【解决方案2】:

简短但坦率地说不是很好的答案

使用slice!覆盖原地变量,相当于

input_text = input_text.slice # etc.

如果您改用普通的旧slice,它不会覆盖input_text

更长且坦率地说更好的答案

在 Ruby 中,嵌套四层的代码通常是一种气味。让我们重构一下,根本不需要重置循环。

我们将使用 Ruby 的内置文件处理模块来读取行,而不是用换行符分割文件。如果我们多次运行它,记住它(||= 运算符)可能会阻止它在每次引用它时重新加载文件。

def dictionary
  @dict ||= File.open('/path/to/dictionary')
end

我们还可以在打开文件时立即将所有单词变成小写,因为在原始示例中每个字符都是单独小写的。

def downcased_dictionary
  @dict ||= File.open('/path/to/dictionary').each(&:downcase)
end

接下来,我们将使用 Ruby 的内置文件和字符串函数,包括#each_char,进行比较并输出结果。我们不需要将任何输入转换为数组(根本!),因为#include? 处理字符串,#each_char 迭代字符串的字符。

我们将字符串拆分分解为自己的方法,这样循环逻辑和字符串逻辑可以更清楚地理解。

最后,通过使用#slice 而不是#slice!,我们不会覆盖input_text,并且完全避免以后需要重置变量。

def base_word(input)
  input_text = input.to_s # Coerce in case it's not a string
  # Read through each line in the dictionary
  dictionary.each do |word|
    word.each_char {|char| slice_base_word(input_text, char) }
  end
end

def slice_base_word(input, char)
  input.slice(input.index(char)) if input.include?(char)
end

【讨论】:

  • 谢谢,马特。我对此投了赞成票,因为这是一个非常详细且经过深思熟虑的答案。我现在还在通读它——但作为 Ruby 的初学者,这非常有帮助,因为它引入了一些我可能需要一段时间才能发现的想法。
  • 感谢您缺少有关问题的上下文,但这并不能完全解决我手头的问题,因此我将 Sergio 标记为正确答案。再次感谢您向我展示了一些将来会派上用场的想法。
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 2014-08-06
  • 2013-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多