2013-11-05 126 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方法的數組。