Python:元组过滤器

Python:元组过滤器,python,filter,tuples,Python,Filter,Tuples,我有两个元组列表。我想要一个新的列表,其中包含l2的每个成员和l1的每个成员,这些成员不以l2中的相同元素开头 我使用了for循环,输出正常 我的问题是:如何使用筛选函数或列表理解 def ov(l1, l2): l3=l1.copy() for i in l2: for j in l1: if i[0]==j[0]: l3.pop(l3.index(j)) print (l3+l2)

我有两个元组列表。我想要一个新的列表,其中包含l2的每个成员和l1的每个成员,这些成员不以l2中的相同元素开头

我使用了for循环,输出正常

我的问题是:如何使用筛选函数或列表理解

def ov(l1, l2):

    l3=l1.copy()    
    for i in l2:

        for j in l1:

            if i[0]==j[0]:
                l3.pop(l3.index(j))

    print (l3+l2)            

ov([('c','d'),('c','e'),('a','b'),('a', 'd')], [('a','c'),('b','d')])
输出为:

[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]

如果我理解正确,这应该是直截了当的解决方案:

>>> l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]                                                                               
>>> l2 = [('a','c'),('b','d')]                                                                                                    
>>>                                                                                                                               
>>> starters = set(x for x, _ in l2)                                                                                              
>>> [(x, y) for x, y in l1 if x not in starters] + l2                                                                             
[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
这可以推广到使用较长的元组


下面是一种使用
过滤器的方法:

from operator import itemgetter

f = itemgetter(0)
zval = set(map(itemgetter(0), l2))

list(filter(lambda tup: f(tup) not in zval, l1)) + l2

[('c', 'd'), ('c', 'e'), ('a', 'c'), ('b', 'd')]
或:


Filter是一个函数,它返回函数的所有真返回的列表,用作
过滤器(function(),迭代器)

我做这件事是为了做这件事。Lambda可能有点混乱,如果你不理解它,请保持警惕,我会重新制作它

列表理解是一个“三元运算符”,如果你熟悉的话,为了在一行中列出一个列表

l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
l2 = [('a','c'),('b','d')]

l3 = [l1[n] for n in range(len(l1)) if l1[n][0] not in [l2[i][0] for i in range(len(l2))]]+l2
print(l3)
这段代码可以做到这一点,但一开始是压倒性的。让我解释一下它的作用。
l1[n]表示范围内的n(len(l1)
遍历l1中的所有对,以查看是否可以添加它们。这是在if返回True时完成的。
l1[n][0]不在
中取第一项,如果在以下列表的任何元素中不存在,则返回True。
[l2[i][0]for i in range(len(l2))]
从l2的所有第一个元素创建一个列表。 根据要求添加
+l2

作为奖励,我将解释如何在同一场景中使用else,以防您需要另一个结果

l1 = [('c','d'),('a','b'),('c','e'),('a', 'd')]
l2 = [('a','c'),('b','d')]

l3 = [l1[n] if l1[n][0] not in [l2[i][0] for i in range(len(l2))] else ("not", "you") for n in range(len(l1))]+l2
print(l3)
正如您所看到的,我必须切换操作符的顺序,但是按照它应该的方式工作,以l1的正确顺序添加它们(为了显示,我更改了顺序)


我无法测试,但在
for
循环中,
索引
弹出
发出警报。这在其他示例中是否可靠工作?如果我理解正确,可以通过使用(有序)字典轻松解决:
d=dict(l1);d.update(l2)
。如有必要,您可以将字典转换回元组列表。@roganjosh我很感激您的提醒。我尝试了一些其他示例,效果很好。我建议将
f=itemgetter(0)
作为第一行,然后在整个过程中使用
f
。为什么要使用
range(len())
什么时候可以在理解中使用元组解包?老实说,这是C语言的老习惯。不过,这是一个较低的级别,让初学者能够理解列表是如何工作的。实际上,我也会使用解包。你有
('not','you')
在您的最终输出中,我还认为您的方法不适合初学者,因为它不太容易阅读。对初学者来说,更深层次的理解总是更好的,因为它可以避免以后出现问题。我已经解释了所有代码的作用,如果读者不清楚,可以对它们进行重新表述。你说“不”是什么意思,“你”)?看看你在图片中发布的输出,你能更好地解释一下
x代表x,在l2
中的含义吗?@PedroPinto它是元组解包。我本可以写
set(x代表x,y代表l2)
,但按照惯例
是用来表示“这个名字不会被使用”。
def compare(one, two):
    for i in two:
        if i[0]==one[0]:
            print("yes:", one,two)
            return False
    return True

l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
l2 = [('a','c'),('b','d')]

one_liner = lambda n: compare(l1[n], l2)  # where n is the tuple in the first list
lets_filter = list(filter(one_liner, range(len(l1))))

final_list = l2.copy()
for i in lets_filter:
    final_list.append(l1[i])

print(final_list)
l1 = [('c','d'),('c','e'),('a','b'),('a', 'd')]
l2 = [('a','c'),('b','d')]

l3 = [l1[n] for n in range(len(l1)) if l1[n][0] not in [l2[i][0] for i in range(len(l2))]]+l2
print(l3)
l1 = [('c','d'),('a','b'),('c','e'),('a', 'd')]
l2 = [('a','c'),('b','d')]

l3 = [l1[n] if l1[n][0] not in [l2[i][0] for i in range(len(l2))] else ("not", "you") for n in range(len(l1))]+l2
print(l3)