根据每个子列表中的第三项删除列表中的重复项

2024-09-30 18:12:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个列表,看起来像:

c = [['470', '4189.0', 'asdfgw', 'fds'],
     ['470', '4189.0', 'qwer', 'fds'],
     ['470', '4189.0', 'qwer', 'dsfs fdv'] 
      ...]

c大约有30000个内部列表。我想做的是消除重复的基础上的每一个内部清单第四项。所以上面的列表如下所示:

^{pr2}$

以下是我目前所掌握的情况:

d = [] #list that will contain condensed c
d.append(c[0]) #append first element, so I can compare lists
for bact in c: #c is my list of lists with 30,000 interior list
    for items in d:
        if bact[3] != items[3]:
            d.append(bact)  

我想这应该行得通,但它总是跑来跑去。我让它跑了30分钟,然后杀了它。我不认为这个程序需要这么长时间,所以我猜我的逻辑有问题。在

我觉得创建一个全新的列表是相当愚蠢的。任何帮助将不胜感激,请随时挑剔,因为我正在学习。如果我的词汇不正确,也请改正。在


Tags: in列表foritems基础listslistappend
3条回答

使用熊猫。我想你也有更好的列名。在

c = [['470', '4189.0', 'asdfgw', 'fds'],
     ['470', '4189.0', 'qwer', 'fds'],
     ['470', '4189.0', 'qwer', 'dsfs fdv']]
import pandas as pd
df = pd.DataFrame(c, columns=['col_1', 'col_2', 'col_3', 'col_4'])
df.drop_duplicates('col_4', inplace=True)
print df

^{pr2}$

我会这样做的:

seen = set()
cond = [x for x in c if x[3] not in seen and not seen.add(x[3])]

说明:

seen是一个集合,它跟踪每个子列表中已经遇到的第四个元素。 cond是压缩列表。如果x[3](其中xc中的子列表)不在seen中,x将被添加到{}中,x[3]将被添加到{}。在

seen.add(x[3])将返回None,因此not seen.add(x[3])将始终是{},但是只有当{}是{}时,才会计算该部分,因为Python使用短路求值。如果对第二个条件求值,它将始终返回True,并产生将x[3]添加到seen的副作用。下面是另一个正在发生的事情的示例(print返回{}并具有打印某些内容的“副作用”):

^{pr2}$

当前代码中存在一个重大的逻辑缺陷:

for items in d:
    if bact[3] != items[3]:
        d.append(bact)  

这将为d中与不匹配的每个项将bact添加到d。对于最小的修复,您需要切换到:

^{pr2}$

如果d中的所有项不匹配,则添加一次bact。我怀疑这将意味着你的代码在更合理的时间内运行。在


除此之外,一个明显的性能改进(速度提升,尽管是以内存使用为代价)是保留到目前为止看到的第四个元素。对集合的查找使用散列,因此成员资格测试(突出显示)将更快。在

d = []
seen = set()
for bact in c:
    if bact[3] not in seen: # membership test
        seen.add(bact[3])
        d.append(bact)

相关问题 更多 >