Python获取唯一列表项

时间:2017-12-05 12:27:11

标签: python multithreading list multiprocessing

我有一个包含数百万个项目的词典列表,我想只提取列表中没有相同键名的唯一项目,是否有更快的方式使用线程或其他东西并行检查而不是顺序,我的代码如下

注意:我的列表是字典列表,每个字典都有不同的键,但它们可能具有相同的键['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)

2 个答案:

答案 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架构。