Ruby on rails 如何计算Ruby中的最高词频

Ruby on rails 如何计算Ruby中的最高词频,ruby-on-rails,ruby,rspec,rspec-rails,Ruby On Rails,Ruby,Rspec,Rspec Rails,我一直在为Coursera Rails简介课程做这项作业。我们的任务是编写一个程序,计算文本文件中的最大字频。已指示我们创建一种方法,该方法: 计算单个单词在给定内容中出现的最大次数,并存储在最高\u wf\u计数中 识别使用次数最多的单词,并将其存储在最高的单词中 当我运行提供给我们的rspec测试时,有一个测试失败了。我打印了输出以查看问题所在,但未能解决 以下是我的代码、rspec测试以及我得到的结果: class LineAnalyzer attr_accessor :highes

我一直在为Coursera Rails简介课程做这项作业。我们的任务是编写一个程序,计算文本文件中的最大字频。已指示我们创建一种方法,该方法:

  • 计算单个单词在给定内容中出现的最大次数,并存储在
    最高\u wf\u计数中
  • 识别使用次数最多的单词,并将其存储在
    最高的单词中
  • 当我运行提供给我们的rspec测试时,有一个测试失败了。我打印了输出以查看问题所在,但未能解决

    以下是我的代码、rspec测试以及我得到的结果:

    class LineAnalyzer
    
      attr_accessor :highest_wf_count
      attr_accessor :highest_wf_words
      attr_accessor :content
      attr_accessor :line_number
    
      def initialize(content, line_number)
        @content = content
        @line_number = line_number
        @highest_wf_count = 0
        @highest_wf_words = highest_wf_words
        calculate_word_frequency
      end
      def calculate_word_frequency()
        @highest_wf_words = Hash.new(0)
        @content.split.each do |word|
          @highest_wf_words[word.downcase!] += 1
          if @highest_wf_words.has_key?(word)
            @highest_wf_words[word] += 1 
          else
            @highest_wf_words[word] = 1
          end
          @highest_wf_words.sort_by{|word, count| count}
          @highest_wf_count = @highest_wf_words.max_by {|word, count| count}
        end
      end
      def highest_wf_count()
        p @highest_wf_count
      end
    end
    
    这是rspec代码:

    require 'rspec'
    
    describe LineAnalyzer do
      subject(:lineAnalyzer) { LineAnalyzer.new("test", 1) }
    
      it "has accessor for highest_wf_count" do
        is_expected.to respond_to(:highest_wf_count) 
      end 
      it "has accessor for highest_wf_words" do
        is_expected.to respond_to(:highest_wf_words) 
      end
      it "has accessor for content" do
        is_expected.to respond_to(:content) 
      end
      it "has accessor for line_number" do
        is_expected.to respond_to(:line_number) 
      end
      it "has method calculate_word_frequency" do
        is_expected.to respond_to(:calculate_word_frequency) 
      end
      context "attributes and values" do
      it "has attributes content and line_number" do
        is_expected.to have_attributes(content: "test", line_number: 1) 
      end
      it "content attribute should have value \"test\"" do
        expect(lineAnalyzer.content).to eq("test")
      end
      it "line_number attribute should have value 1" do
        expect(lineAnalyzer.line_number).to eq(1)
      end
    end
    
      it "calls calculate_word_frequency when created" do
        expect_any_instance_of(LineAnalyzer).to receive(:calculate_word_frequency)
        LineAnalyzer.new("", 1) 
      end
    
      context "#calculate_word_frequency" do
        subject(:lineAnalyzer) { LineAnalyzer.new("This is a really really really cool cool you you you", 2) }
    
        it "highest_wf_count value is 3" do
          expect(lineAnalyzer.highest_wf_count).to eq(3)
        end
        it "highest_wf_words will include \"really\" and \"you\"" do
          expect(lineAnalyzer.highest_wf_words).to include 'really', 'you'
        end
        it "content attribute will have value \"This is a really really really cool cool you you you\"" do
          expect(lineAnalyzer.content).to eq("This is a really really really cool cool you you you")
        end
        it "line_number attribute will have value 2" do
          expect(lineAnalyzer.line_number).to eq(2)
        end
      end
    end
    
    这是rspec输出:

    13 examples, 1 failure
    
    Failed examples:
    
    rspec ./course01/module02/assignment-Calc-Max-Word-Freq/spec/line_analyzer_spec.rb:42 # LineAnalyzer#calculate_word_frequency highest_wf_count value is 3
    
    我的输出:

    #<LineAnalyzer:0x00007fc7f9018858 @content="This is a really really really cool cool you you you", @line_number=2, @highest_wf_count=[nil, 10], @highest_wf_words={"this"=>2, nil=>10, "is"=>1, "a"=>1, "really"=>3, "cool"=>2, "you"=>3}>
    
    #2,nil=>10,“是”=>1,“是”=>1,“真的”=>3,“酷”=>2,“你”=>3}>
    
  • 根据测试字符串,字数不正确
  • 哈希中包含“nil”
  • 哈希没有按值(计数)进行应有的排序
  • 我尝试了几种方法来解决这些问题,但没有任何效果。我又看了一遍讲课材料,但找不到任何有用的东西,而且讨论板上也没有经常监控学生的问题

    nil来自于
    downcase

    这将修改在位字符串,如果没有任何更改,则返回
    nil
    。 如果你说“这很奇怪”,那么你是对的

    排序

    sort_by
    返回一个新对象(散列、数组等),并且不修改方法的接收者。您需要重新分配或使用
    排序依据

    unsorted = [3, 1, 2]
    sorted = unsorted.sort
    
    p unsorted # => [3, 1, 2]
    p sorted # => [1, 2, 3]
    
    unsorted.sort!
    p unsorted # => [1, 2, 3]
    
    错误字数

    一旦你纠正了这两个错误,它就会看起来更好。请注意,该方法返回的不是单个整数,而是一个包含单词和计数的两元素数组,因此它应该是这样的:
    [“really”,6]

    简化事情:

    如果您可以使用ruby 2.7,那么就有了方便的
    Enumerable#tally
    方法

    %w(foo foo bar foo baz foo).tally
    => {"foo"=>4, "bar"=>1, "baz"=>1}
    

    根据:

    唐卡斯!(*args)公共

    下调str的内容,如果没有更改,则返回nil


    由于
    .downcase的这种意外行为
    method,如果单词已经全部小写,那么您将增加此行中出现的
    nil

    @最高单词[word.downcase!]+=1
    
    测试也失败了,因为
    @highest_wf_words.max_by{word,count | count}
    返回一个包含计数和单词的数组,而我们只想获得计数

    通过测试的简化
    计算单词频率
    方法如下所示:

    def计算单词频率()
    @最高\u wf\u字=散列。新(0)
    @content.split.each do|单词|
    #我们不必检查这个词以前是否存在
    #因为我们在@highest\u wf\u words散列中将0设置为默认值
    #使用.downcase代替.downcase!
    @最高单词[word.downcase]+=1
    #仅提取计数,然后获取最大值
    @highest_wf_count=@highest_wf_words.map{| word,count | count}.max
    结束
    结束
    
    请参见“”。我们需要演示问题的最小代码、复制问题的最小输入数据以及问题本身的预期输出。请确保构造一个。请注意,这三个词都很重要:它应该只是一个示例,您不应该发布整个实际代码,而应该创建一个简单的示例来演示您的问题。此外,它应该是最小的,也就是说,它不应该包含任何不是证明问题绝对需要的内容。(大多数初学者的问题都可以用不到5行简单的代码来演示。)而且它应该是可复制的,这意味着如果我复制粘贴并运行代码,我会看到与你看到的完全相同的问题。“如果你说“这很奇怪”,那么你是对的(IMHO)。”–我宁愿说,甚至关心一个变异方法的返回值都是很奇怪的。我认为在很多方面都很奇怪:-),但我希望返回
    self
    ,这样它就可以被链接起来。“由于
    .downcase!
    方法的这种意外行为”–这并不是真的意外。这也是所有类似方法的表现。而且,它是一种变异的方法,为什么您甚至希望它在第一种情况下有一个返回值?
    %w(foo foo bar foo baz foo).tally
    => {"foo"=>4, "bar"=>1, "baz"=>1}