我的任务是找到列表中每个单词的出现频率。有两种方法。
方法1
def f(words):
wdict = {}
for word in words:
if word not in wdict:
wdict[word] = 0
wdict[word] += 1
return wdict
方法2
def g(words):
wdict = {}
for word in words:
try:
wdict[word] += 1
except KeyError:
wdict[word] = 1
为什么方法2高效?并非在这两种情况下,哈希函数调用的数量都与此http://blackecho.github.io/blog/programming/2016/03/23/python-underlying-data-structures.html相矛盾?
答案 0 :(得分:1)
让我们模拟几种情况。
例如:“一只鸟在飞”
words = ["A", "bird", "is", flying"]
您的第一种方法:
对于每个单词,它将在字典中搜索3次,因此将访问总计3 * {len(words)
或3 * 4 = 12
第二种方法 如果找不到,它将仅搜索2次;否则1次:所以2 * 4 = 8
从理论上讲,两者的时间复杂度相同。
更新:
感谢Thierry Lathuille指出。实际上,方法1应该比方法2更有效。Python字典使用哈希图,因此访问键的复杂度为O(n),但通常情况下为O(1)。而且cpython的实现非常有效。另一方面,try / catch异常处理很慢。
您可以在方法1中使用defaultdict以获得更简洁的代码。
答案 1 :(得分:1)
这取决于输入。如果平均而言,大多数单词已经在字典中,那么您将不会有很多例外。如果大多数单词都是唯一的,则异常的开销会使第二种方法变慢。
答案 2 :(得分:0)
有几种方法可以解决此问题。您可以使用循环并仍然获得预期的答案。我专注于两种方法:
列表理解
wordstring = 'it was the best of times it was the worst of times '
wordstring += 'it was the age of wisdom it was the age of foolishness'
wordlist = wordstring.split()
# Count each word
wordfreq = [wordlist.count(w) for w in wordlist] # a list comprehension
# Convert to set to remove repetitions
frequencies=set(zip(wordlist, wordfreq))
print(frequencies)
输出:
{('of', 4), ('best', 1), ('the', 4), ('worst', 1), ('age', 2), ('wisdom', 1), ('it', 4), ('was', 4), ('times', 2), ('foolishness', 1)}
方法二:标准库
import collections
wordstring = 'it was the best of times it was the worst of times '
wordstring += 'it was the age of wisdom it was the age of foolishness'
wordlist = wordstring.split()
# Count frequency
freq=collections.Counter(wordlist)
print(freq)
输出:
Counter({'it': 4, 'was': 4, 'the': 4, 'of': 4, 'times': 2, 'age': 2, 'best': 1, 'worst': 1, 'wisdom': 1, 'foolishness': 1})
选择的方法取决于您正在处理的文本的大小。上面的方法适用于较小的文本。
答案 3 :(得分:0)
有两个主要区别:
in
操作,而方法2将在可能的情况下直接更新。 这最终取决于输入,但是如果重复次数足够多,则操作会更少。
示例:
让我们只看一下这里的代码,以获取一般想法(而不是实际操作)。
['a', 'a']
Method1
1-wdict中没有'a'-True
2-分配“ a”
3-更新'a'
4-'a'not dict-假
5-更新'a'
Method2
1-访问'a'
2-错误
3-将“ a”直接分配给1
4-更新“ a”(第二个“ a”)
尽管这些步骤并不完全是执行时要执行的操作数量,但它们表示Method2更精简并且执行的“步骤”更少。