Python 计算列表1中的项目在列表2中出现的次数
我有两份清单:Python 计算列表1中的项目在列表2中出现的次数,python,python-3.x,Python,Python 3.x,我有两份清单: 1. ['a', 'b', 'c'] 2. ['a', 'd', 'a', 'b'] 我希望字典输出如下: {'a': 2, 'b': 1, 'c': 0} 我已经做到了: #b = list #1 #words = list #2 c = {} for i in b: c.update({i:words.count(i)}) 但它非常慢,我需要处理像10MB的txt文件 编辑:完整代码,当前正在测试未使用的导入 import string import os i
1. ['a', 'b', 'c']
2. ['a', 'd', 'a', 'b']
我希望字典输出如下:
{'a': 2, 'b': 1, 'c': 0}
我已经做到了:
#b = list #1
#words = list #2
c = {}
for i in b:
c.update({i:words.count(i)})
但它非常慢,我需要处理像10MB的txt文件
编辑:完整代码,当前正在测试未使用的导入
import string
import os
import operator
import time
from collections import Counter
def getbookwords():
a = open("wu.txt", encoding="utf-8")
b = a.read().replace("\n", "").lower()
a.close()
b.translate(string.punctuation)
b = b.split(" ")
return b
def wordlist(words):
a = open("wordlist.txt")
b = a.read().lower()
b = b.split("\n")
a.close()
t = time.time()
#c = dict((i, words.count(i)) for i in b )
c = Counter(words)
result = {k: v for k, v in c.items() if k in set(b)}
print(time.time() - t)
sorted_d = sorted(c.items(), key=operator.itemgetter(1))
return(sorted_d)
print(wordlist(getbookwords()))
尝试使用并将b
移动到集合
,而不是列表
:
from collections import Counter
c = Counter(words)
b = set(b)
result = {k: v for k, v in c.items() if k in b}
另外,如果你可以懒洋洋地读单词,而不是创建一个应该更快的中间列表
计数器
提供您想要的功能(计算项目),并且根据集合过滤结果
使用哈希,这应该快得多。由于速度目前是一个问题,因此可能值得考虑不通过列表来计算您想要计算的每件事情。set()
函数允许您仅使用列表中的单词中的唯一键
在任何情况下,速度都要记住的一点是行unique\u words=set(b)
。如果没有这一点,将对列表进行一次完整的遍历,以便在每次迭代中从b
创建一个集合,无论您使用哪种类型的数据结构
c = {k:0 for k in set(words)}
for w in words:
c[w] += 1
unique_words = set(b)
c = {k:counts[k] for k in c if k in unique_words}
或者,defaultdicts
可以用来消除一些初始化
from collections import defaultdict
c = defaultdict(int)
for w in words:
c[w] += 1
unique_words = set(b)
c = {k:counts[k] for k in c if k in unique_words}
为了完整性起见,我确实喜欢其他答案中基于计数器的解决方案(如Reut Sharabani)。代码更干净,尽管我还没有对其进行基准测试,但如果内置计数类比使用字典的自制解决方案更快,我也不会感到惊讶
from collections import Counter
c = Counter(words)
unique_words = set(b)
c = {k:v for k, v in c.items() if k in unique_words}
您可以在生成器上使用collection.Counter
,该生成器使用set
查找跳过被忽略的键
from collections import Counter
keys = ['a', 'b', 'c']
lst = ['a', 'd', 'a', 'b']
unique_keys = set(keys)
count = Counter(x for x in lst if x in unique_keys)
print(count) # Counter({'a': 2, 'b': 1})
# count['c'] == 0
请注意,count['c']
未打印,但在计数器中默认情况下仍为0
以下是我刚刚在repl中给出的一个示例。假设列表2中没有重复项。我们使用字典创建一个哈希表。对于列表中匹配两个的每个项,我们创建一个键值对,该项为键,并将值设置为0
接下来我们遍历第二个列表,对于每个值,我们检查值是否已经定义,如果已经定义,则使用键增加值。否则,我们忽略
尽可能少的迭代次数。每个列表中的每个项目只命中一次
x=[1,2,3,4,5];
z=[1,2,2,2,1];
y={};
对于x中的n:
y[n]=0//将列表中每个项目的值设置为零
对于z中的n:
if(y中的n)://如果我们已经在散列中定义了值,则递增1
y[n]+=1;
打印(y)
@makone,以上答案是可以理解的。您还可以尝试下面的代码示例,该示例使用Python的collections
模块中的计数器()
你可以试试看
Python代码»
输出»
你能告诉我你是怎么读这个文件的吗?如果不需要的话,不要把它读到一个列表中。“慢”有多慢?它需要60多秒。。。目前正在测试第一个答案,时间太长@MakaloneLOgman不,这是不一样的,它稍微更有效,因为它使用生成器理解来跳过不在列表中的单词的计数keys@MakaloneLOgman那是因为我忘了在循环外创建集合。此解决方案将非常快速。列表1中键的位可以使用类似于set(list1)
的散列结构加快,就像在其他答案中一样。这可能对OP的原始数据很有效,但恶意反例会使其性能异常糟糕。@Musgrave,感谢您的建议和编辑。我认为list1将被视为唯一的一组键。使用set()很好,因为用户还可以使用可能导致性能问题的重复元素。谢谢!令人惊讶的是,我有时会忘记简单的问题解决方案。
from collections import Counter
list1 = ['a', 'b', 'c']
list2 = ['a', 'd', 'a', 'b']
counter = Counter(list2)
d = {key: counter[key] for key in set(list1)}
print(d)
{'a': 2, 'c': 0, 'b': 1}