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

1 投票
3 回答
2091 浏览
提问于 2025-04-18 10:17

我有一个列表,里面又包含了很多小列表,长得像这样:

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

这个列表大约有30,000个小列表。我想做的是根据每个小列表的第4个项目来去掉重复的内容。所以上面的列表看起来应该是这样的:

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

这是我目前的代码:

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分钟,然后就停止了。我觉得这个程序不应该花这么长时间,所以我猜我的逻辑可能有问题。

我感觉创建一个全新的列表来存放这些小列表可能不是个好主意。任何帮助都非常感谢,欢迎大家挑剔,因为我还在学习。如果我的用词不对,也请帮我纠正。

3 个回答

1

使用pandas库。我猜你有更好的列名。

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

  col_1   col_2   col_3     col_4
0   470  4189.0  asdfgw       fds
2   470  4189.0    qwer  dsfs fdv
1

你的代码里有一个很明显的逻辑错误:

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

这段代码会把 bact 加到 d 中,每当 d 里的某个项目不匹配时就加一次。要简单修复这个问题,你需要改成:

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

这样就能在 所有d 项目都不匹配时只加一次 bact。我猜这样改后,你的代码运行会更合理一些。


此外,还有一个明显的性能提升(速度会更快,但会占用更多内存)就是保持一个你已经看到的第四个元素的 set。在这个集合中查找使用的是哈希,所以检查某个元素是否在其中(这里强调的部分)会快很多。

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

我会这样做:

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 会被添加到 cond 中,同时 x[3] 也会被添加到 seen 中。

seen.add(x[3]) 会返回 None,所以 not seen.add(x[3]) 总是会是 True,不过这一部分只有在 x[3] not in seenTrue 的时候才会被判断,因为 Python 会使用短路评估。如果第二个条件被判断,它总是会返回 True,并且会有一个副作用,就是把 x[3] 加入到 seen 中。这里还有一个例子说明发生了什么(print 返回 None,并且有一个“副作用”,就是打印出一些东西):

>>> False and not print('hi')
False
>>> True and not print('hi')
hi
True

撰写回答