制限事項
辞書の使用を拒否した場合、アルゴリズムには多くの計算が必要になります。その上では、1回だけ出現するキーワード(例: "karl")とくだらないシーケンス(例: "e2bo")を区別することはできません。私の解決策は最善の努力であり、URLのリストにキーワードが複数回含まれている場合にのみ機能します。
基本的な考え方
単語は、少なくとも3文字の頻繁に出現する文字のシーケンスであると想定しています。これにより、文字「o」が最も人気のある単語になるのを防ぎます。
基本的な考え方は次のとおりです。
- n文字のシーケンスをすべてカウントし、複数回発生する1つを選択します。
- より大きなシーケンスの一部であるすべてのシーケンスをカットします。
- 人気順に並べると、問題の解決に近い解決策が得られます。(読者への演習として残します)
コード内
import operator
sentences = ["davidbobmike1joe" , "mikejoe2bobkarl", "joemikebob", "bobjoe", "bobbyisawesome", "david", "bobbyjoe"];
dict = {}
def countWords(n):
"""Count all possible character sequences/words of length n occuring in all given sentences"""
for sentence in sentences:
countWordsSentence(sentence, n);
def countWordsSentence(sentence, n):
"""Count all possible character sequence/words of length n occuring in a sentence"""
for i in range(0,len(sentence)-n+1):
word = sentence[i:i+n]
if word not in dict:
dict[word] = 1;
else:
dict[word] = dict[word] +1;
def cropDictionary():
"""Removes all words that occur only once."""
for key in dict.keys():
if(dict[key]==1):
dict.pop(key);
def removePartials(word):
"""Removes all the partial occurences of a given word from the dictionary."""
for i in range(3,len(word)):
for j in range(0,len(word)-i+1):
for key in dict.keys():
if key==word[j:j+i] and dict[key]==dict[word]:
dict.pop(key);
def removeAllPartials():
"""Removes all partial words in the dictionary"""
for word in dict.keys():
removePartials(word);
for i in range(3,max(map(lambda x: len(x), sentences))):
countWords(i);
cropDictionary();
removeAllPartials();
print dict;
出力
>>> print dict;
{'mike': 3, 'bobby': 2, 'david': 2, 'joe': 5, 'bob': 6}
読者へのいくつかの課題
- 印刷する前に、辞書を値で並べ替えます。(Python辞書を値で並べ替えます)
- この例では、「bob」は6回出現し、2回は「bobby」の部分的な単語です。これに問題があるかどうかを判断し、必要に応じて修正します。
- キャピタライゼーションを考慮に入れてください。