Ruby - 访问实例变量时出错

Ruby - Error accessing instance variables

我正在学习Ruby,我在编写程序时遇到了问题。

我有一个 class "LineAnalyzer",它有 4 个参数(2 个提供,2 个计算)。两个计算参数是:@high_wf_count(整数)和@high_wf_words(数组)。 然后,我有这个:

class Solution < LineAnalyzer
    attr_reader :analyzers, 
                :highest_count_across_lines, 
                :highest_count_words_across_lines

    def initialize
        @analyzers = [] 
    end

    def analyze_file
        File.foreach('test.txt') do |line|
            @analyzers << LineAnalyzer.new(line.chomp,@analyzers.length+1)
        end 
    end

    def calculate_line_with_highest_frequency
        @highest_count_words_across_lines = []
        @highest_count_across_lines = @analyzers.max_by do 
            |a| a.instance_variable_get(:@highest_wf_count)
        end .instance_variable_get(:@highest_wf_count)

        @highest_count_words_across_lines << @analyzers.each do
            |a| a.instance_variable_get(:@highest_wf_count) == @highest_count_across_lines
        end .instance_variable_get(:@highest_wf_words)
    end    
end

问题是我无法按照我所做的方式将数组 @highest_wf_count 附加到 @highest_count_words_across_lines(returns nil)。但是,我以前以同样的方式完美地采用了整数 @highest_wf_count

谁能告诉我哪里出了问题?

提前致谢!

看来你的问题出在这段代码中:

@highest_count_words_across_lines << @analyzers.each do
    |a| a.instance_variable_get(:@highest_wf_count) == @highest_count_across_lines
end .instance_variable_get(:@highest_wf_words)

最好格式为:

@highest_count_words_across_lines << @analyzers.each do |analyzer|
  analyzer.instance_variable_get(:@highest_wf_count) == @highest_count_across_lines
end.instance_variable_get(:@highest_wf_words)

这里的问题是您在 :each 方法的结果上调用 .instance_variable_get(:@highest_wf_words)

上面几行,您正在做类似的事情,您在 :max_by 方法的结果上调用 .instance_variable_get(:@highest_wf_count),它正在运行。

:max_by:each的区别在于:max_byreturns是一个分析器,而:eachreturns是@analyzers 它正在迭代。

当您对该数组调用 :instance_variable_get(:@highest_wf_words) 时,它返回 nil 因为数组不会有名为 :@highest_wf_words

的实例变量

那就是你的问题所在。

旁注:

使用 :instance_variable_get 通常不是好的做法。我建议添加到您的分析器 class attr_reader :highest_wf_words, :highest_wf_count

那么,您可以直接调用 analyzer.highest_wf_words

而不是调用 analyzer.instance_variable_get(:@highest_wf_words)

这比需要(或应该)复杂得多。

为什么Solution subclass LineAnalyzer?为什么要使用 instance_variable_get?您应该在 LineAnalyzer class 上使用 attr_reader 定义 getter 方法,这样您就可以调用方法而不是使用 instance_variable_get,这是一种只能用作不得已。

我认为你应该在继续之前解决这个问题。

当您使用 attr_reader 创建实例方法时,计算最大值变得非常简单:

highest_count_across_lines = @analyzers.map(&:highest_wf_count).max

我认为您的错误可能是由这些行引起的:

 @highest_count_words_across_lines << @analyzers.each do
            |a| a.instance_variable_get(:@highest_wf_count) == @highest_count_across_lines
        end .instance_variable_get(:@highest_wf_words)

我建议简化此代码,错误可能会出现在您面前。您真的是想将 each 返回的值附加到 @highest_count_words_across_lines 吗?这将是一个分析器数组。数组 class 当然没有名为 :@highest_wf_words.

的变量

同样,我认为您确实需要简化此代码。

这里发生了很多事情,大部分代码都是由于在编写 Ruby 时违背规律而产生的。使用 instance_variable_get 绝对是最后的手段。仅仅伸手进入一个对象并拉出一个变量被认为是非常粗鲁的。它会产生丑陋且不受欢迎的相互依赖关系。如果那个其他对象想给你那个值,它就会有一个方法来访问它。

我对您尝试做的事情的看法可以归结为这样的事情:

def highest_frequency
  @analyzers.map do |a|
    a.highest_wf_count
  end.sort.last
end

Analyzer实现highest_wf_count作为一个方法,即使它只是一个attr_reader。这使您可以灵活地更改计算该值的方式和时间。也许你不需要在对象初始化的时候做。也许它是在另一个线程中完成的,或者它是延迟评估的。

尽可能尝试将您的代码构建为一系列直接转换。尽量不要创建复杂的、分支的、丑陋的比较。尽可能依赖 Enumerable,它通常有一个方法可以完全满足您的需求,或者两个方法可以完美地结合使用。