我的问题如下。我有一个很长的url列表,例如:
www.foo.com/davidbobmike1joe
www.foo.com/mikejoe2bobkarl
www.foo.com/joemikebob
www.foo.com/bobjoe
我需要将该列表中的所有条目(url)相互比较,提取这些url的子域中的关键字(在本例中:david, joe, bob, mike, karl)并按频率对它们排序。我一直在阅读一些库,比如nltk。然而,这里的问题是没有空格来独立地标记每个单词。对如何完成这项工作有什么建议吗?
限制
如果你拒绝使用字典,你的算法将需要大量的计算。在此之上,不可能区分只出现一次的关键字(例如:"karl")和蹩脚的序列(例如:"e2bo")。我的解决方案将是一个最好的努力,只会工作,如果你的URL的列表包含关键字多次。
基本思路
我假设一个单词是一个至少3个字符的频繁出现的字符序列。这就阻止了字母"o"成为最流行的单词。
基本思想如下:
- 计算所有n个字母序列,并选择多次出现的一次。
- 剪掉所有大序列的一部分。
- 按受欢迎程度排序,你就有了一个接近解决问题的解决方案。(留给读者练习)
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"的部分单词。确定这是否有问题,并在必要时修复它。
- 考虑大小写
概述
您可以使用以下代码提取名称,传入[david, bob等]的列表:
是否有一种简单的方法从python的无空格句子中生成可能的单词列表?
然后用collections.Counter
得到频率
from Bio import trie
import string
from collections import Counter
def get_trie(words):
tr = trie.trie()
for word in words:
tr[word] = len(word)
return tr
def get_trie_word(tr, s):
for end in reversed(range(len(s))):
word = s[:end + 1]
if tr.has_key(word):
return word, s[end + 1: ]
return None, s
def get_trie_words(s):
names = ['david', 'bob', 'karl', 'joe', 'mike']
tr = get_trie(names)
while s:
word, s = get_trie_word(tr, s)
yield word
def main(urls):
d = Counter()
for url in urls:
url = "".join(a for a in url if a in string.lowercase)
for word in get_trie_words(url):
d[word] += 1
return d
if __name__ == '__main__':
urls = [
"davidbobmike1joe",
"mikejoe2bobkarl",
"joemikebob",
"bobjoe",
]
print main(urls)
<标题> 结果Counter({'bob': 4, 'joe': 4, 'mike': 3, 'karl': 1, 'david': 1})
标题>标题>