2013-11-05 67 views
-1

对于课程项目,我们应该采用已发表的论文并创建一个算法来创建以文本为单位的所有词的列表,同时排除停用词。我试图列出所有独特单词(在整个文本中)以及它们的出现频率。这是我的一个文本行创建的算法:不包括停止词出现的唯一频率

x = l[125] #Selecting specific line in the text 
p = Array.new() # Assign new array to variable p 
p = x.split # Split the array 
for i in (0...p.length) 
    if(p[i] != "the" and p[i] != "to" and p[i] != "union" and p[i] != "political") 
    print p[i] + " " 
    end 
end 
puts 

这个程序的输出是一个句子(从线125)。我应该使用冒泡排序吗?我将如何修改它以对相等长度的字符串进行排序(或者是不相关的)?

+0

您需要的算法 - 唯一性,排序,过滤 - 已经在Ruby的Array类中实现。如果这是你课程的目的,那么也可以直接重新实施它们 - 你最好的选择就是谷歌算法的名称。大多数Ruby编程人员只会使用内置函数 - 请参阅http://ruby-doc.org/core-2.0.0/Array.html并查看方法列表 –

+0

您还应该了解“Hash”类(或一般意义上的关联数组,如果您尝试从头开始实施),您可以将其用于过滤和计算词频。 –

回答

1

我想说你有一个好的开始,因为你是Ruby的新手。你问是否应该使用冒泡排序。我想你正在考虑将一个单词的多次出现分组,然后通过数组来计算它们。这会起作用,但还有其他一些方法更容易,更像“类Ruby”。 (我的意思是说,他们利用语言的强大功能,同时更自然。)

让我们专注于统计单行中的唯一字。一旦你可以做到这一点,你应该能够轻松地将其推广到多行。

第一种方法:使用哈希

第一种方法是使用哈希值。 h = {}创建一个新的空的。散列的键将是单词,其值将是每个单词出现在该行中的次数。例如,如果单词“猫”出现9次,我们将有h["cat"] = 9,正是你需要的。为了构造这个散列,我们看到该行中的每个单词w是否已经在散列中。这是哈希如果

h[w] != nil 

如果是,我们增加字数:

h[w] = h[w] + 1 

或只是

h[w] += 1 

如果它不是在哈希,我们加字到这样的散列:

h[w] = 1 

那m是指合同,我们可以这样做:

if h[w] 
    h[w] += 1 
else 
    h[w] = 1 
end 

注意,这里if h[w]相同if h[w] != nil

其实,我们可以用一个技巧来使这更简单。如果我们创建这样的哈希:

h = Hash.new(0) 

然后,我们添加的任何没有值的键将被分配默认值为零。这样我们就不必检查这个单词是否已经在散列中;我们简单地写

h[w] += 1 

如果w不在哈希,h[w]将增加,并把它初始化为0,然后+= 1将它递增到1。很酷,呃?

让我们把所有这些放在一起。假设

line = "the quick brown fox jumped over the lazy brown fox" 

我们这个字符串转换成数组与String#split方法:

arr = line.split # => ["the", "quick", "brown", "fox", "jumped", \ 
         "over", "the", "lazy", "brown", "fox"] 

然后

h = Hash.new(0) 
arr.each {|w| h[w] += 1} 
h # => {"the"=>2, "quick"=>1, "brown"=>2, "fox"=>2, "jumped"=>1, "over"=>1, "lazy"=>1} 

我们就大功告成了!

第二种方法:每当你想一个数组,散列或其它集合族元素使用Enumerable#group_by方法

,该group_by方法应该浮现在脑海中。

要将group_by应用于快速棕色狐狸阵列,我们提供了一个包含分组标准的块,在这种情况下,该分组标准本身就是单词。这将产生一个散列:

g = arr.group_by {|e| e} 
# => {"the"=>["the", "the"], "quick"=>["quick"], "brown"=>["brown", "brown"], \ 
#  "fox"=>["fox", "fox"], "jumped"=>["jumped"], "over"=>["over"], "lazy"=>["lazy"]} 

接下来要做的是转换散列值到字(例如,转换到["the", "the"]2)的出现的次数。要做到这一点,我们可以创建一个新的空哈希h,并添加哈希对吧:

h = {} 
g.each {|k,v| h[k] = v.size} 
h # => {"the"=>2, "quick"=>1, "brown"=>2, "fox"=>2, "jumped"=>1, "over"=>1, "lazy"=>1 

一件事

你有这样的代码片段:

if(p[i] != "the" and p[i] != "to" and p[i] != "union" and p[i] != "political") 
    print p[i] + " " 
    end 

这里有几种方法可以使这一点更清洁,都使用上面的散列h

第一种方式

skip_words = %w[the to union political] # => ["the", "to", "union", "political"] 
h.each {|k,v| (print v + ' ') unless skip_words.include?(k)} 

第二种方式

h.each |k,v| 
    case k 
    when "the", "to", "union", "political" 
    next 
    else 
    puts "The word '#{k}' appears #{v} times." 
    end 
end 

编辑解决您的评论。试试这个:

p = "The quick brown fox jumped over the quick grey fox".split 
freqs = Hash.new(0) 
p.each {|w| freqs[w] += 1} 
sorted_freqs = freqs.sort_by {|k,v| -v} 
sorted_freqs.each {|word, freq| puts word+' '+freq.to_s} 
=> 
quick 2 
fox 2 
jumped 1 
The 1 
brown 1 
over 1 
the 1 
grey 1 

通常情况下,ypu不会排序散列;而你会先将其转换为一个数组:

sorted_freqs = freqs.to_a.sort_by {|x,y| v}.reverse 

sorted_freqs = freqs.to_a.sort_by {|x,y| -v} 

现在sorted_freqs是一个数组,而不是一个哈希值。最后一行保持不变。一般来说,最好不要依赖哈希的顺序。事实上,在Ruby 1.9.2之前,哈希并没有被排序。如果顺序很重要,请使用数组或将哈希转换为数组。尽管如此,您可以对散列值进行从最小到最大的排序,或者(如我所做的那样)对散列值的负值进行从最大到最小的排序。请注意,没有Enumerable#reverseHash#reverse。或者(有很多方法对皮肤使用Ruby猫),你可以排序v然后用Enumerable#reverse_each

sorted_freqs.reverse_each {|word, freq| puts word+' '+freq.to_s} 

最后,您可以消除临时变量sorted_freqs(必要的,因为没有Enumerable#sort_by!方法),通过链接最后两条语句:

freqs.sort_by {|k,v| -v}.each {|word, freq| puts word+' '+freq.to_s} 
+0

我试着创建一个新的哈希来解决这个问题,它似乎并没有工作。我一直在意料之中|错误。 freqs = Hash.new(0) > p.each {| word | freqs [p] + = 1} > freqs.sort_by {| x,y | y} > freqs.reverse! > freqs.each {| word,freq |把word +''+ freq.to_s} – user2955139

+0

我已经通过编辑我的答案来解决你的评论。您应该能够明白为什么您的代码无法与我添加的代码进行比较,但如果您仍然有疑问,请不要犹豫,问问。 –

1

你应该看看Ruby的枚举类。你很少用红宝石做for x in y

word_list = ["the", "to", "union", "political"] 
l[125].split.each do |word| 
    print word + " " unless word_list.include?(word) 
end 

为了计算,排序和所有东西看着group_by方法,也许sort_by方法的数组。