【问题标题】:python lambda list filtering with multiple conditions具有多个条件的python lambda列表过滤
【发布时间】:2016-11-16 22:51:50
【问题描述】:

我对使用 lambda 过滤列表的理解是,过滤器将返回列表中为 lambda 函数返回 True 的所有元素。在这种情况下,对于以下代码,

inputlist = []
inputlist.append(["1", "2", "3", "a"])
inputlist.append(["4", "5", "6", "b"])
inputlist.append(["1", "2", "4", "c"])
inputlist.append(["4", "5", "7", "d"])

outputlist = filter(lambda x: (x[0] != "1" and x[1] != "2" and x[2] != "3"), inputlist)
for item in outputlist: print(item)

输出应该是

['4', '5', '6', 'b']
['1', '2', '4', 'c']
['4', '5', '7', 'd']

但我得到的输出是

['4', '5', '6', 'b']
['4', '5', '7', 'd']

如果我使用,我会得到预期的输出

outputlist = filter(lambda x: (x[0] != "1" or x[1] != "2" or x[2] != "3"), inputlist)

我在这里做什么傻事?还是我的理解不正确?

【问题讨论】:

  • 我们无法判断您的理解是否正确,因为您没有告诉我们您期望lambda 函数做什么。如果您使用and 加入条件,除非所有条件都为真,否则它不会评估为true。如果您使用or 加入条件,如果其中一个条件为真,它将评估为true
  • 现在我真的感觉很笨!我想我需要停止工作,去打麻袋。抱歉浪费了你们的时间。

标签: python list lambda filter multiple-conditions


【解决方案1】:

x = ['1', '2', '4', 'c'],所以x[1]=='2',这使得表达式(x[0] != "1" and x[1] != "2" and x[2] != "3") 被评估为False

当条件由and 连接时,它们仅在所有条件都是True 时返回True,如果它们由or 连接,当它们中的第一个被评估为时返回True True.

【讨论】:

    【解决方案2】:
    ['1', '2', '4', 'c']
    

    条件失败

    x[0] != "1"
    

    还有

    x[1] != "2"
    

    而不是使用or,我相信更自然和可读的方式是:

    lambda x: (x[0], x[1], x[2]) != ('1','2','3')
    

    出于好奇,我比较了三种方法,呃……比较,结果符合预期:切片列表最慢,使用元组更快,使用布尔运算符最快。更准确地说,比较的三种方法是

    list_slice_compare = lambda x: x[:3] != [1,2,3]
    
    tuple_compare = lambda x: (x[0],x[1],x[2]) != (1,2,3)
    
    bool_op_compare = lambda x: x[0]!= 1 or x[1] != 2 or x[2]!= 3
    

    和结果分别:

    In [30]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; list_slice_compare = lambda x: x[:3] != [1,2,3]", stmt="list_slice_compare(rand_list)").repeat()
    Out[30]: [0.3207617177499742, 0.3230015148823213, 0.31987868894918847]
    
    In [31]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; tuple_compare = lambda x: (x[0],x[1],x[2]) != (1,2,3)", stmt="tuple_compare(rand_list)").repeat()
    Out[31]: [0.2399928924012329, 0.23692036176475995, 0.2369164465619633]
    
    In [32]: timeit.Timer(setup="import timeit,random; rand_list = [random.randint(1,9) for _ in range(4)]; bool_op_compare = lambda x: x[0]!= 1 or x[1] != 2 or x[2]!= 3", stmt="bool_op_compare(rand_list)").repeat()
    Out[32]: [0.144389363900018, 0.1452672728203197, 0.1431527621755322]
    

    【讨论】:

    • 如果你使用!=右侧的列表,那么你可以使用左侧x[:3] != ["1", "2", "3"]的切片
    【解决方案3】:

    过滤器的作用与应有的完全一样。第一种情况

    lambda x: (x[0] != "1" and x[1] != "2" and x[2] != "3")
    

    过滤器只“接受”第一个元素不是 1 且第二个元素不是 2 且第三个元素不是 3 的列表。因此列表 ['1', '2', '4', 'c'] 不会通过,因为它的第一个元素是 1。相反,

    lambda x: (x[0] != "1" or x[1] != "2" or x[2] != "3")
    

    将接受第一个元素不是 1 或第二个元素不是 2 或第三个元素不是 3 的任何列表。因此,['1', '2', '4', 'c'] 将被接受,因为它的第三个元素不是 3。

    【讨论】:

      【解决方案4】:

      嗯,['1', '2', '4', 'c'] 不满足x[0] != "1" 的条件,也不满足x[1] != "2" 的条件。

      【讨论】:

        猜你喜欢
        • 2022-01-19
        • 2020-03-23
        • 2019-08-25
        • 1970-01-01
        • 1970-01-01
        • 2017-10-11
        • 2017-11-02
        • 2013-07-21
        • 1970-01-01
        相关资源
        最近更新 更多