我可以在Ruby的String类中使用String类的方法吗?

时间:2013-11-07 23:52:43

标签: ruby string hash metaprogramming

我在ruby中对字符串对象的新方法应该返回字符串中每个字符的计数的哈希值(从.txt文件加载),我可能试图以简单的方式去做,但是如果没有传递对象,我似乎无法使其工作。我想知道是否有办法在不传递字符串的情况下执行此操作。任何帮助将不胜感激。

这是我的代码

class String
  def frequency
    Object.downcase
    Object.gsub("\n", " ")
    h = {}
    h["A:"] = Object.count('a')
    h["B:"] = Object.count('b')
    h["C:"] = Object.count('c')
    h["D:"] = Object.count('d')
    h["E:"] = Object.count('e')
    h["F:"] = Object.count('f')
    h["G:"] = Object.count('g')
    h["H:"] = Object.count('h')
    h["I:"] = Object.count('i')
    h["J:"] = Object.count('j')
    h["K:"] = Object.count('k')
    h["L:"] = Object.count('l')
    h["M:"] = Object.count('m')
    h["N:"] = Object.count('n')
    h["O:"] = Object.count('o')
    h["P:"] = Object.count('p')
    h["Q:"] = Object.count('q')
    h["R:"] = Object.count('r')
    h["S:"] = Object.count('s')
    h["T:"] = Object.count('t')
    h["U:"] = Object.count('u')
    h["V:"] = Object.count('v')
    h["W:"] = Object.count('w')
    h["K:"] = Object.count('x')
    h["Y:"] = Object.count('y')
    h["Z"] = Object.count('z')
return h
end
end

4 个答案:

答案 0 :(得分:2)

听起来你在谈论self,这是引用当前对象的ruby关键字。请注意,如果您只是调用该方法,则会隐含self。所以要使用你的例子

class String
  def frequency
    count('a')
  end
end

将返回字符串

a的数量
"asdfa".frequency #=> 2

只是一个注释,但您当前的方法非常重复,您可能想要利用循环来减少代码量。你也不算大写字母:)

答案 1 :(得分:1)

以下是我使用的版本,它是Rosetta Letter Frequency的完整副本:

#!/usr/bin/env ruby
def letter_frequency(string)
    freq = Hash.new(0)
    string.each_char.lazy.grep(/[[:alpha:]]/).map(&:upcase).each_with_object(freq) do |char, freq_map|
        freq_map[char] += 1
    end
end

在ruby中,你可以打开课程并添加方法,例如:

class String
   def my_method
       my_method_code
   end
end

然后你只需调用方法string.my_method。但是在你的情况下,我宁愿使用Ruby module。这是一个代码示例,非常类似于类但更干净的imho:

#!/usr/bin/env ruby

module MyString
    def self.letter_frequency(string)
        freq = Hash.new(0)
        string.each_char.lazy.grep(/[[:alpha:]]/).map(&:upcase).each_with_object(freq) do |char, freq_map|
            freq_map[char] += 1
        end
        return freq
    end
end

p MyString.letter_frequency('absd')

模块更适合在项目中添加自己的类,避免名称冲突和创建混合。

答案 2 :(得分:1)

而不是一个非常长的,非DRY方法迭代你的对象26次,如何使用一些Ruby:

def frequency
  Hash[downcase.gsub(/[^a-z]/,'').chars.group_by(&:to_s).map{|char, group| ["#{char.upcase}:", group.size]}]
end

如果你发现它更容易阅读(并在API [1]中查找方法),你可以将它分成不同的行:

def frequency
  intermediate_variable = downcase
  intermediate_variable = intermediate_variable.gsub(/[^a-z]/,'') # only keep a-z characters
  intermediate_variable = intermediate_variable.chars.group_by(&:to_s) # split the string into its component characters and then group that array by the characters (run this on an array to see what it does :-)  could also have written it `.group_by{|e|e}`
  intermediate_variable = intermediate_variable.map{|char, group| ["#{char.upcase}:", group.size]} # map the array of grouped characters into an array of character and counts (formatting the 'character' how you would like your hash key configured
  Hash[intermediate_variable] # make a hash of the characters and their counts
end

[1] http://ruby-doc.org/core-2.0.0/Enumerable.html http://ruby-doc.org/core-2.0.0/String.html

答案 3 :(得分:1)

我只想创建一个这样的哈希:

class String 
  def frequency
    chars.each_with_object(Hash.new(0)) do |char, h|
      h["#{char.upcase}:"] += 1 if char[/[[:alpha:]]/]
    end
  end
end