如何基于另一个嵌套列表中的元素对嵌套列表中的元素进行重复数据删除? 或者,遍历一列并根据另一列中的元素列表删除重复项是否更有意义?
Column 1
R1 = [foo, bar, baz, qux,]
R2 = [Cat, Dog, Frog, Bird]
R3 = [Salad, Potato, Pizza, Soda
Column 2
R1 = [bar, quuz, quux, qux]
R2 = [Fish, Dog, Cow]
R3 = [Potato, Milk, Apple, Pizza]
我只关心保持listB
唯一的元素,顺序无关紧要
Final Column
R1 = [quuz, quux]
R2 = [Fish, Cow]
R3 = [Milk, Apple]
实际列表如下所示,并包含以下字符:\,()
[Youth Counselor / Worker, Nutrition / Dietetic Technician,Mathematician,Tailor / Seamstress,Librarian]
我必须将每个元素都保护为字符串,以便在这种情况下无法使用平面列表
答案 0 :(得分:3)
如果顺序无关紧要:
zip()
function将两个输入列表中的嵌套列表配对。list()
这可以表示为单线:
[list(set(b) - set(a)) for a, b in zip(listA, listB)]
如果输出中的嵌套集可以接受,则可以放弃list(...)
调用:
[set(b) - set(a) for a, b in zip(listA, listB)]
演示:
>>> listA = [['A', 'B', 'C', 'D', 'E'], [1, 2, 3, 4, 5], ['!', '@', '#', '$', '%']]
>>> listB = [['E', 'A', 'T', 'F', 'W'], [5, 6, 8, 2, 9], ['@', '^', '&', '#', '*']]
>>> [list(set(b) - set(a)) for a, b in zip(listA, listB)]
[['W', 'F', 'T'], [8, 9, 6], ['^', '&', '*']]
>>> [set(b) - set(a) for a, b in zip(listA, listB)] # without list(...)
[{'W', 'F', 'T'}, {8, 9, 6}, {'^', '&', '*'}]
如果您改变主意并确定顺序对输出至关重要,那么:
listA
中的每个嵌套列表转换为一次一次,以进行更快的遏制测试。 value in listobject
每次都必须迭代listobject
,而value in setobject
使用散列来测试在O(1)(恒定)时间内是否包含。listB
中给定嵌套列表中的值,并针对listA
中的匹配集测试该值,仅保留未出现在相应集中的值。为此,请使用列表理解。map()
来处理listA
嵌套列表到集合的转换。这样有助于避免每次您测试listB
的嵌套列表中的值时都创建新集。因此,可以保留输入顺序的单行代码是:
[[v for v in nested_b if v not in set_a] for set_a, nested_b in zip(map(set, listA), listB)]
zip()
函数将listA
(通过map(set, listA)
)产生的集合与listB
的嵌套列表配对,因此我们可以在最外层的每次迭代中将它们一起使用列表理解。然后,嵌套列表推导会过滤每个嵌套列表的值:
>>> [[v for v in nested_b if v not in set_a] for set_a, nested_b in zip(map(set, listA), listB)]
[['T', 'F', 'W'], [6, 8, 9], ['^', '&', '*']]
答案 1 :(得分:0)
使用sets
,您可以执行以下操作:
listA = [["A","B","C","D","E"],[1,2,3,4,5],["!","@","#","$","%"]]
listB = [["E","A","T","F","W"],[5,6,8,2,9],["@","^","&","#","*"]]
print([list(set(listB[i]).difference(set(listA[i]))) for i in range(len(listB))])
给我:
[['F', 'W', 'T'], [8, 9, 6], ['^', '&', '*']]
注意:它将更改列表的顺序。
编辑:
或者按照@ user3483203的建议,比这更可靠的解决方案是:
[[list(b - a) for a, b in zip(map(set, listA), map(set, listB))]
答案 2 :(得分:0)
假设您要按列表索引进行检查
result_list = []
for listA_nest,listB_nest zip(listA,listB):
result_list.append(list(filter(lambda listB_el: listB_el not in listA_nest ,listB_nest))
类似的东西应该起作用,可能有更好的解决方案。
单行解决方案:
result_list = [list(filter(lambda listB_el: listB_el not in set(listA_nest) ,listB_nest)) for listA_nest,listB_nest in zip(listA,listB)]
答案 3 :(得分:0)
假设您正在检查A和B中的相应列表,则可能希望zip
将它们保持在一起,并且可以使用in
方法来检查成员资格:
listFinal = []
for l1, l2 in zip(listA, listB):
l = [x for x in l2 if x not in l1]
listFinal.append(l)
[['T', 'F', 'W'], [6, 8, 9], ['^', '&', '*']]
虽然更快的方法是使用set
,它使您可以快速删除重复的集合并测试O(1)而不是O(N)的成员资格。
listFinal = []
for l1, l2 in zip(listA, listB):
# set subtraction here will remove all elements present in l1 from l2
l = set(l2) - set(l1)
listFinal.append(list(l))
[['T', 'F', 'W'], [8, 9, 6], ['*', '&', '^']]
或者,如果愿意,可以一行
listFinal = [list(set(l2) - set(l1)) for l1, l2 in zip(listA, listB)]
显示zip的工作方式:
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
for x, y in zip(a, b):
print(x, y)
1 5
2 6
3 7
4 8
它将为传递给它的每个可迭代对象生成相应的元素组。
设置减法:
a = set('a', 'b', 'c')
b = set('b', 'c', 'd')
a - b
{'a'}