Python - 我的频率功能效率低下
Python - My frequency function is inefficient
我正在编写一个函数,该函数 returns 单词列表中出现次数最多的单词的出现次数。
def max_frequency(words):
"""Returns the number of times appeared of the word that
appeared the most in a list of words."""
words_set = set(words)
words_list = words
word_dict = {}
for i in words_set:
count = []
for j in words_list:
if i == j:
count.append(1)
word_dict[i] = len(count)
result_num = 0
for _, value in word_dict.items():
if value > result_num:
result_num = value
return result_num
例如:
words = ["Happy", "Happy", "Happy", "Duck", "Duck"]
answer = max_frequency(words)
print(answer)
3
但是这个函数在处理列表中的大量单词时会很慢,例如一个250,000个单词的列表需要4分钟以上才能呈现输出。所以我正在寻求帮助来调整它。
我不想导入任何东西。
虽然我完全同意与你的我不想导入任何东西声明相关的评论,但我发现你的问题很有趣,所以让我们试试吧。
您不需要构建 set
。直接用 words
.
words = words = ["Happy", "Happy", "Happy", "Duck", "Duck"]
words_dict = {}
for w in words:
if w in words_dict:
words_dict[w] += 1
else:
words_dict[w] = 1
result_num = max(words_dict.values())
print(result_num)
# 3
要防止为每个唯一单词多次传递列表,您可以简单地迭代一次并为每个计数更新字典值。
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
输出:
>>> print(max(counts.values()))
3
也就是说,使用 defaultdict
而不是 get
或使用 collections.Counter
可以做得更好...限制自己在 Python 中不导入如果您可以选择,那永远不是一个好主意。
例如,使用collections.Counter
:
from collections import Counter
counter = Counter(words)
most_common = counter.most_common(1)
您可以尝试此代码,它的速度提高了大约 760%。
def max_frequency(words):
"""Returns the number of times appeared of the word that
appeared the most in a list of words."""
count_dict = {}
max = 0
for word in words:
current_count = 0
if word in count_dict:
current_count = count_dict[word] = count_dict[word] + 1
else:
current_count = count_dict[word] = 1
if current_count > max:
max = current_count
return max
数据大小与 OP 相似
让我们从单词列表开始
In [55]: print(words)
['oihwf', 'rpowthj', 'trhok', 'rtpokh', 'tqhpork', 'reaokp', 'eahopk', 'qeaopker', 'okp[qrg', 'okehtq', 'pinjjn', 'rq38na', 'aogopire', "apoe'ak", 'apfobo;444', 'jiaegro', '908qymar', 'pe9irmp4', 'p9itoijar', 'oijor8']
然后将这些词随机组合成一篇文章
In [56]: from random import choice
In [57]: text = ' '.join(choice(words) for _ in range(250000))
可能有不同的方法
从文中我们可以得到文中的单词列表(注意,wl
和words
有很大的不同...)
In [58]: wl = text.split()
我们想从这个列表中提取一个字典,或者一个类似字典的对象,以及出现次数,我们有很多选择。
第一个选项,我们构建一个包含 wl
中所有不同单词的字典,并将每个键的值设置为零,然后我们在单词列表上进行另一个循环以计算出现次数
In [59]: def count0(wl):
wd = dict(zip(wl,[0]*len(wl)))
for w in wl: wd[w] += 1
return wd
....:
第二个选项,我们从一个空字典开始,并使用允许默认值
的get()
方法
In [60]: def count1(wl):
wd = dict()
for w in wl: wd[w] = wd.get(w, 0)+1
return wd
....:
第三个也是最后一个选项,我们使用标准库
的组件
In [61]: def count2(wl):
from collections import Counter
wc = Counter(wl)
return wc
....:
一种方法是否优于其他方法?
哪个最好?你最喜欢的那个……总之,这是各自的时间安排
In [62]: %timeit count0(wl) # start with a dict with 0 values
10 loops, best of 3: 82 ms per loop
In [63]: %timeit count1(wl) # uses .get(key, 0)
10 loops, best of 3: 92 ms per loop
In [64]: %timeit count2(wl) # uses collections.Counter
10 loops, best of 3: 43.8 ms per loop
正如预期的那样,最快的过程是使用 collections.Counter
的过程,但我有点惊讶地注意到第一个选项(两次传递数据)比第二个更快。 .. 我的猜测(我的意思是:猜测)是所有对新值的测试都是在实例化字典时完成的,可能在一些 C
代码中。
我正在编写一个函数,该函数 returns 单词列表中出现次数最多的单词的出现次数。
def max_frequency(words):
"""Returns the number of times appeared of the word that
appeared the most in a list of words."""
words_set = set(words)
words_list = words
word_dict = {}
for i in words_set:
count = []
for j in words_list:
if i == j:
count.append(1)
word_dict[i] = len(count)
result_num = 0
for _, value in word_dict.items():
if value > result_num:
result_num = value
return result_num
例如:
words = ["Happy", "Happy", "Happy", "Duck", "Duck"]
answer = max_frequency(words)
print(answer)
3
但是这个函数在处理列表中的大量单词时会很慢,例如一个250,000个单词的列表需要4分钟以上才能呈现输出。所以我正在寻求帮助来调整它。
我不想导入任何东西。
虽然我完全同意与你的我不想导入任何东西声明相关的评论,但我发现你的问题很有趣,所以让我们试试吧。
您不需要构建 set
。直接用 words
.
words = words = ["Happy", "Happy", "Happy", "Duck", "Duck"]
words_dict = {}
for w in words:
if w in words_dict:
words_dict[w] += 1
else:
words_dict[w] = 1
result_num = max(words_dict.values())
print(result_num)
# 3
要防止为每个唯一单词多次传递列表,您可以简单地迭代一次并为每个计数更新字典值。
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
输出:
>>> print(max(counts.values()))
3
也就是说,使用 defaultdict
而不是 get
或使用 collections.Counter
可以做得更好...限制自己在 Python 中不导入如果您可以选择,那永远不是一个好主意。
例如,使用collections.Counter
:
from collections import Counter
counter = Counter(words)
most_common = counter.most_common(1)
您可以尝试此代码,它的速度提高了大约 760%。
def max_frequency(words):
"""Returns the number of times appeared of the word that
appeared the most in a list of words."""
count_dict = {}
max = 0
for word in words:
current_count = 0
if word in count_dict:
current_count = count_dict[word] = count_dict[word] + 1
else:
current_count = count_dict[word] = 1
if current_count > max:
max = current_count
return max
数据大小与 OP 相似
让我们从单词列表开始
In [55]: print(words)
['oihwf', 'rpowthj', 'trhok', 'rtpokh', 'tqhpork', 'reaokp', 'eahopk', 'qeaopker', 'okp[qrg', 'okehtq', 'pinjjn', 'rq38na', 'aogopire', "apoe'ak", 'apfobo;444', 'jiaegro', '908qymar', 'pe9irmp4', 'p9itoijar', 'oijor8']
然后将这些词随机组合成一篇文章
In [56]: from random import choice
In [57]: text = ' '.join(choice(words) for _ in range(250000))
可能有不同的方法
从文中我们可以得到文中的单词列表(注意,wl
和words
有很大的不同...)
In [58]: wl = text.split()
我们想从这个列表中提取一个字典,或者一个类似字典的对象,以及出现次数,我们有很多选择。
第一个选项,我们构建一个包含 wl
中所有不同单词的字典,并将每个键的值设置为零,然后我们在单词列表上进行另一个循环以计算出现次数
In [59]: def count0(wl):
wd = dict(zip(wl,[0]*len(wl)))
for w in wl: wd[w] += 1
return wd
....:
第二个选项,我们从一个空字典开始,并使用允许默认值
的get()
方法
In [60]: def count1(wl):
wd = dict()
for w in wl: wd[w] = wd.get(w, 0)+1
return wd
....:
第三个也是最后一个选项,我们使用标准库
的组件In [61]: def count2(wl):
from collections import Counter
wc = Counter(wl)
return wc
....:
一种方法是否优于其他方法?
哪个最好?你最喜欢的那个……总之,这是各自的时间安排
In [62]: %timeit count0(wl) # start with a dict with 0 values
10 loops, best of 3: 82 ms per loop
In [63]: %timeit count1(wl) # uses .get(key, 0)
10 loops, best of 3: 92 ms per loop
In [64]: %timeit count2(wl) # uses collections.Counter
10 loops, best of 3: 43.8 ms per loop
正如预期的那样,最快的过程是使用 collections.Counter
的过程,但我有点惊讶地注意到第一个选项(两次传递数据)比第二个更快。 .. 我的猜测(我的意思是:猜测)是所有对新值的测试都是在实例化字典时完成的,可能在一些 C
代码中。