我有一个包含数百万个项目的词典列表,我想只提取列表中没有相同键名的唯一项目,是否有更快的方式使用线程或其他东西并行检查而不是顺序,我的代码如下
注意:我的列表是字典列表,每个字典都有不同的键,但它们可能具有相同的键['name']值,如果匹配我应该只带一个
例如: lst = [{'name':'x','bar':1,'foo':2},{'name','z','foo':3,'bar':5},{'name ':x','bar':33,'foo':10}] 这里有两个字典有相同的名字等于x所以我只会在新列表中保存一个 new_lst = [{'name':'x','bar':1,'foo':2},{'name','z','foo':3,'bar':5}]
new_lst = []
for x in lst:
flag = False
for n in new_lst:
if x['name'] == n['name']:
flag = True
break
if not flag:
new_lst.append(x)
答案 0 :(得分:1)
可重复示例:
因此,我为一个大型字典构建了一个可重复的示例来计算一个好的基准:
import string
import random
lst = []
for i in range(10000):
lst.append({'name':random.choice(string.letters)+random.choice(string.letters),
'foo':random.choice(range(100)),
'bar':random.choice(range(100))})
您这样做的方式:
然后我在函数中编译你的方式:
def your_fun(lst):
new_lst = []
for x in lst:
flag = False
for n in new_lst:
if x['name'] == n['name']:
flag = True
break
if not flag:
new_lst.append(x)
return(new_lst)
更快捷的方式:
通过存储已在列表中看到的名称来更快地限制循环次数(循环速度慢)。
def my_fun(lst):
new_lst = []
seens_names = []
for x in lst:
if not x['name'] in seens_names:
new_lst.append(x)
seens_names.append(x['name'])
return(new_lst)
<强>基准:强>
我执行基准测试:
%timeit your_fun(lst)
1 loop, best of 3: 1.14 s per loop
%timeit my_fun(lst)
10 loops, best of 3: 143 ms per loop
因此,只需通过压制一个循环,就可以将时间成本除以10 ......
<强>结论:强>
在考虑多线程之前,尽可能避免循环会使代码更快。
可能还有其他方法可以不断提高效果。
在研究多线程之前的另一个改进是在cython中编写这个任务。
答案 1 :(得分:0)
由于您没有提供示例,因此很难准确捕获您想要的内容,但您可能会发现以下内容:
a = [{'bar': 1, 'foo': 2}, {'foobar': 3, 'bar': 5}]
a = {k: v for subdict in a for k, v in subdict.items()}
print(a) # {'bar': 5, 'foo': 2, 'foobar': 3}
# ^ 'bar' appears only once (but value could be either 1 or 5)
# ^ 'foobar' is taken from the 1st dict. Does not exist in 2nd.
# ^ 'foo' is taken from the 2nd dict. Does not exist in 1st.
我在这里建议的是list
的展平并将其缩减为单个dict
。重复项将自动覆盖(订单无法保证)。
或者,您可以通过以下方式实现相同的目标(更容易理解):
res = a[0]
for d in a[1:]:
res.update(d) # every dict is <<applied>> to the previous one as an update.
print(res) # {'bar': 5, 'foo': 2, 'foobar': 3}
注意强>
我的上述解决方案假设您不关心保留dict
- in - list
架构。