我正在学习Ruby,而且在编写程序时遇到了问题。
我有一个“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
(它返回nil
)。但是,我之前已经以完全相同的方式取整数@highest_wf_count
。
谁能告诉我问题出在哪里?
提前致谢!
答案 0 :(得分:2)
看来你的问题出现在这段代码中:
@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)
这里的问题是您在.instance_variable_get(:@highest_wf_words)
方法的结果上调用了:each
。
上面几行,您正在执行类似的操作,在.instance_variable_get(:@highest_wf_count)
方法的结果上调用:max_by
,它正在运行。
:max_by
和:each
之间的区别在于:max_by
返回单个分析器,而:each
返回正在迭代的@analyzers
数组。
当你在该数组上调用:instance_variable_get(:@highest_wf_words)
时,它返回nil
,因为数组不会有名为:@highest_wf_words
的实例变量
这就是你的问题所在。
使用:instance_variable_get
通常不是好习惯。我建议您添加到您的分析器类attr_reader :highest_wf_words, :highest_wf_count
然后,您只需拨打analyzer.instance_variable_get(:@highest_wf_words)
analyzer.highest_wf_words
答案 1 :(得分:2)
这里有很多内容,大多数代码都是在编写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,通常会有一种方法可以完全按照你想要的方式,或者两种方法完美地完成工作。
答案 2 :(得分:1)
这比它需要(或应该是)更复杂。
为什么Solution
子类LineAnalyzer
?你为什么要使用instance_variable_get
?您应该在LineAnalyzer类上使用attr_reader
定义getter方法,这样您就可以调用方法而不是使用instance_variable_get
,这是一种只能作为最后手段使用的强力方法。
我认为你应该在继续之前解决这个问题。
当您使用attr_reader创建实例方法时,计算max变得非常简单:
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吗?这将是一组分析仪。当然,Array类没有名为:@highest_wf_words
的变量。
同样,我认为你真的需要简化这段代码。