我有一个列表如下:
c = [['470', '4189.0', 'asdfgw', 'fds'],
['470', '4189.0', 'qwer', 'fds'],
['470', '4189.0', 'qwer', 'dsfs fdv']
...]
c
有大约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分钟,然后杀了它。我不认为该程序需要这么长时间,所以我猜测我的逻辑有问题。
我觉得创建一个全新的列表列表非常愚蠢。任何帮助将不胜感激,请随时挑剔,因为我正在学习。如果不正确,请更正我的词汇。
答案 0 :(得分:5)
我会这样做:
seen = set()
cond = [x for x in c if x[3] not in seen and not seen.add(x[3])]
说明:
seen
是一个跟踪已经遇到的每个子列表的第四个元素的集合。
cond
是精简列表。如果x[3]
(其中x
是c
中的子列表)不在seen
中,x
将添加到cond
和{{} 1}}将添加到x[3]
。
seen
将返回seen.add(x[3])
,因此None
始终为not seen.add(x[3])
,但只有在True
为x[3] not in seen
时才评估该部分因为Python使用短路评估。如果评估了第二个条件,它将始终返回True
并产生将True
添加到x[3]
的副作用。这是发生了什么的另一个例子(seen
返回print
并且具有打印内容的“副作用”):
None
答案 1 :(得分: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)
如果bact
中的所有项目都不匹配,请添加d
一次。我怀疑这意味着你的代码会在更合理的时间内运行。
最重要的是,一个显而易见的性能改进(速度提升,尽管以内存使用为代价)将保留到目前为止您已经看到的set
个第四个元素。集合上的查找使用哈希值,因此成员资格测试(突出显示)将更快。
d = []
seen = set()
for bact in c:
if bact[3] not in seen: # membership test
seen.add(bact[3])
d.append(bact)
答案 2 :(得分:0)
使用熊猫。我假设你有更好的列名。
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