Ruby:如何计算字母的频率

时间:2017-12-09 18:19:51

标签: ruby

帮助:做一个频率方法:计算每个字母出现在“str”中的频率,并将输出分配给“字母”。该方法应将小写和大写计为相同的字母。但我有关于NoMethodError的错误:未定义的方法 谢谢

这是我的代码

use Phalcon\Http\Response; 
use Phalcon\Mvc\Model\Criteria; 
use Phalcon\Mvc\Model\Query\BuilderInterface; 
use Phalcon\Di\InjectionAwareInterface; 
use Phalcon\Mvc\Model\Resultset; use Phalcon\Ext\Mailer\Manager; 
use Phalcon\Ext\Mailer\Message;

class EmailController extends Phalcon\Mvc\Controller { 
public function initialize() { 
if ($this->request->isPost()) { 
$this->view->disable(); 
} 
}
public function indexAction() {

}

public function sendEmailAction(){
    if ($this->request->isPost()) {

        $config = [
            'driver'   => 'mail',
            'from'         => [
                'email' => 'manager@email.com',
                'name'    => 'Email'
            ]
        ];

        $email = new Phalcon\Ext\Mailer\Message($config);
        return "send";
    }
}
}

错误显示:

class MyString
  attr_accessor :str
  attr_reader :letters

  def initialize
    @str = "Hello World!"
    @letters = Hash.new()
  end
  def frequency
    @letters = @str.split(" ").reduce(@letters) { |h, c| h[c] += 1; h}
  end
  def histogram
    #@letters.each{|key,value| puts "#{key} + ':' + value.to_s + '*' * #{value}" }
  end
end

2 个答案:

答案 0 :(得分:4)

当您尝试将1添加到不存在的哈希值中时,会尝试将1添加到nil,这是不允许的。您可以更改哈希值,使其保留默认值0,而不是nil

@letters = Hash.new(0)

现在,你的程序正在计算单词频率,而不是字母频率(split(" ")分隔空格,而不是每个字符。要对每个字符进行拆分,请使用适当命名的each_char方法。

@letters = @str.each_char.reduce(@letters) { |h, c| h[c] += 1; h}

答案 1 :(得分:1)

每当使用计数哈希(@ Silvio的答案)时,可以改为使用Enumerable#group_by,这就是我在这里所做的。

str = "It was the best of times, it was the worst of times"

str.gsub(/[[:punct:]\s]/, '').
    downcase.
    each_char.
    group_by(&:itself).
    each_with_object({}) { |(k,v),h| h[k] = v.size }
  #=> {"i"=>4, "t"=>8, "w"=>3, "a"=>2, "s"=>6, "h"=>2, "e"=>5,
  #    "b"=>1, "o"=>3, "f"=>2, "m"=>2, "r"=>1}

步骤如下。

a = str.gsub(/[[:punct:]\s]/, '')
  #=> "Itwasthebestoftimesitwastheworstoftimes"
b = a.downcase
  #=> "itwasthebestoftimesitwastheworstoftimes"
e = b.each_char
  #=> #<Enumerator: "itwasthebestoftimesitwastheworstoftimes":each_char>
f = e.group_by(&:itself)
  #=> {"i"=>["i", "i", "i", "i"],
  #    "t"=>["t", "t", "t", "t", "t", "t", "t", "t"],
  #    ...
  #    "r"=>["r"]}
f.each_with_object({}) { |(k,v),h| h[k] = v.size }
   #=> < return value shown above >

让我们仔细看看最后一步。散列f的第一个键值对作为双元素数组传递给块,以及散列h的初始值:

(k,v), h = [["i", ["i", "i", "i", "i"]], {}]
  #=> [["i", ["i", "i", "i", "i"]], {}]

应用消歧(或分解)的规则,我们获得以下内容。

k #=> "i"
v #=> ["i", "i", "i", "i"]
h #=> {}

执行块计算:

h[k] = v.size
  #=> h["i"] = 4

所以现在

h => { "i"=>4 }

下一个键值对与h的当前值一起传递给块:

(k,v), h = [["t", ["t", "t", "t", "t", "t", "t", "t", "t"]], { "i"=>4 }]
  #=> [["t", ["t", "t", "t", "t", "t", "t", "t", "t"]], {"i"=>4}]
k #=> "t"
v #=> ["t", "t", "t", "t", "t", "t", "t", "t"]
h #=> {"i"=>4}
h[k] = v.size
  #=> 8

所以现在

h #=> {"i"=>4, "t"=>8}

其余的计算方法类似。