Python 根据每个子列表中的第三项删除列表列表列表中的重复项
我有一个列表,如下所示:Python 根据每个子列表中的第三项删除列表列表列表中的重复项,python,duplicate-removal,nested-lists,Python,Duplicate Removal,Nested Lists,我有一个列表,如下所示: c = [['470', '4189.0', 'asdfgw', 'fds'], ['470', '4189.0', 'qwer', 'fds'], ['470', '4189.0', 'qwer', 'dsfs fdv'] ...] c有大约30000个内部列表。我想做的是根据每个内部列表的第4项消除重复项。因此,上面的列表如下所示: c = [['470', '4189.0', 'asdfgw', 'fds'],['470', '
c = [['470', '4189.0', 'asdfgw', 'fds'],
['470', '4189.0', 'qwer', 'fds'],
['470', '4189.0', 'qwer', 'dsfs fdv']
...]
c
有大约30000个内部列表。我想做的是根据每个内部列表的第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分钟,然后杀了它。我认为这个程序不应该花这么长时间,所以我猜我的逻辑有问题
我觉得创建一个全新的列表是相当愚蠢的。任何帮助都将不胜感激,请随意挑剔,因为我正在学习。如果不正确,请纠正我的词汇。我会这样做:
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
,并将x[3]
添加到seen
中
seen.add(x[3])
将返回None
,因此not seen.add(x[3])
将始终是True
,但只有当x[3]not in seen
为True时才会对该部分进行求值,因为Python使用短路求值。如果对第二个条件求值,它将始终返回True
,并产生将x[3]
添加到seen
的副作用。下面是另一个正在发生的情况的示例(print
返回None
,并且具有打印某些内容的“副作用”):
我会这样做:
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
,并将x[3]
添加到seen
中
seen.add(x[3])
将返回None
,因此not seen.add(x[3])
将始终是True
,但只有当x[3]not in seen
为True时才会对该部分进行求值,因为Python使用短路求值。如果对第二个条件求值,它将始终返回True
,并产生将x[3]
添加到seen
的副作用。下面是另一个正在发生的情况的示例(print
返回None
,并且具有打印某些内容的“副作用”):
当前代码中存在严重的逻辑缺陷:
for items in d:
if bact[3] != items[3]:
d.append(bact)
这会为d
中不匹配的每个项目向d
添加一次bact
。要获得最低限度的修复,您需要切换到:
for items in d:
if bact[3] == items[3]:
break
else:
d.append(bact)
如果d
中的所有项目不匹配,则添加bact
一次。我怀疑这将意味着您的代码在更合理的时间内运行
最重要的是,一个明显的性能改进(速度提升,尽管这是以内存使用为代价的)是保留迄今为止看到的第四个元素集。集合上的查找使用哈希,因此成员资格测试(突出显示)将更快
d = []
seen = set()
for bact in c:
if bact[3] not in seen: # membership test
seen.add(bact[3])
d.append(bact)
当前代码中存在严重的逻辑缺陷:
for items in d:
if bact[3] != items[3]:
d.append(bact)
这会为d
中不匹配的每个项目向d
添加一次bact
。要获得最低限度的修复,您需要切换到:
for items in d:
if bact[3] == items[3]:
break
else:
d.append(bact)
如果d
中的所有项目不匹配,则添加bact
一次。我怀疑这将意味着您的代码在更合理的时间内运行
最重要的是,一个明显的性能改进(速度提升,尽管这是以内存使用为代价的)是保留迄今为止看到的第四个元素集。集合上的查找使用哈希,因此成员资格测试(突出显示)将更快
d = []
seen = set()
for bact in c:
if bact[3] not in seen: # membership test
seen.add(bact[3])
d.append(bact)
使用熊猫。我想你也有更好的列名
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
使用熊猫。我想你也有更好的列名
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
您如何知道哪些重复项需要删除?您是否考虑过输出中已经存在的第四个元素的单独集合
?这将使成员查找更快。你是对的。我想我目前不需要其他信息。你能直接创建一个“集合”吗?还是我要遍历列表列表创建一个列表,然后调用set函数?@user3754225你可以向集合中添加,不要重复c
两次!你应该看看熊猫。如果(我假设)这不会是您对这些数据进行的最后一次类似于表的操作,那么熊猫将是一项非常好的投资。您在pandas中的操作就是df.drop_duplicates('col_4')
您如何知道哪些重复项需要删除?您是否考虑过输出中已经存在的第四个元素的一个单独的集合
?这将使成员查找更快。你是对的。我想我目前不需要其他信息。你能直接创建一个“集合”吗?还是我要遍历列表列表创建一个列表,然后调用set函数?@user3754225你可以向集合中添加,不要重复c
两次!你应该看看熊猫。如果(我假设)这不会是您对这些数据进行的最后一次类似于表的操作,那么熊猫将是一项非常好的投资。你在pandas中的操作就是df.drop_duplicates('col_4')
我对'And not'感到困惑。这是不是逻辑上等同于“如果”和“那么”等等?还是完全是另外一回事?@user3754225我扩展了解释,我对“与否”感到困惑。这是不是逻辑上等同于“如果”和“那么”等等?还是完全是另外一回事?@user3754225我对解释进行了一点扩展