过滤具有复杂表达式的列表

时间:2015-12-01 16:31:02

标签: python lambda

arr = [[2,6,8],[1,4,7],[3,3,4],[2,4,9],[3,3,7]]

array_analysis = lambda arr=[], evenOdd=True, no_doubles= True:list(i for i in arr if evenOdd == True len(set(i) % 2) if no_doubles == True len(set(i) !> 1)

# test it
print('test array', arr)
for evenOdd, no_doubles in ((True, True), (True, False), (False, True), (False, False)):
    print(evenOdd, no_doubles, array_analysis(arr, evenOdd, no_doubles))

我正在尝试创建一个lambda函数,它将根据条件参数过滤数组列表。

  • 如果所有lambda参数都是True,则返回值应为:[[1,4,7],[2,4,9]],因为没有所有奇数或所有均数在数字集中没有双精度数。

  • 如果no_doublesFalse,则应包括没有全部偶数或没有全部赔率的双打。返回值应为[[1,4,7],[2,4,9],[3,3,4]],不包括设置[3,3,7],因为它都是奇数。

  • 如果oddEvenFalseno_double为false,则返回值应为所有数字,反之亦然。如果oddEvenFalseno_doubleTrue,则返回值应为[[3,3,4],[3,3,7]]

没有lambda

# filters all odd or all even
def oddEven(a):
    return [i for i in a if len(set(np.mod(i, 2)))!=2]

# filters doubles
def no_doubles(a):
    return [i for i in a if len(set(i))!>2]

def all_filters_combined(a):
    return oddEven(a) and no_doubles(a)

这几乎是我正在寻找的,但它不使用lambda,它不允许我选择是否要更改过滤。如何更改此代码以允许我在一个lambda函数中选择过滤器?

1 个答案:

答案 0 :(得分:1)

我相信这可以做你想要的......

arr = [[2,6,8],[1,4,7],[3,3,4],[2,4,9],[3,3,7]]

foo = lambda arr, evenOdd, noDoubles: [ i for i in arr if not (evenOdd and (all(k % 2 == 1 for k in i) or all(k%2 == 0 for k in i))) and not (noDoubles and (len(i) != len(set(i))))]

print(foo(arr, False, False))
print(foo(arr, True, False))
print(foo(arr, False, True))
print(foo(arr, True, True))

 $ python3 foo.py
[[2, 6, 8], [1, 4, 7], [3, 3, 4], [2, 4, 9], [3, 3, 7]]
[[1, 4, 7], [3, 3, 4], [2, 4, 9]]
[[2, 6, 8], [1, 4, 7], [2, 4, 9]]
[[1, 4, 7], [2, 4, 9]]
 $

让我们分解一下。

[ i for i in arr if ... ] - 你可以使用列表推导来做这样的过滤。我们只需确保...根据元素正确评估为TrueFalse

not (evenOdd and (all(k % 2 == 1 for k in i) or all(k%2 == 0 for k in i))) - 这是evenOdd测试。如果evenOddFalse,则语句将短路到True,这意味着不应过滤该元素。如果evenOddTrue,则all(k % 2 == 1 for k in i)会测试i的每个元素是否为奇数(并且下一个测试检查为偶数)。

and - 如果任一测试失败,则应过滤该元素。

not (noDoubles and (len(i) != len(set(i)))) - 如果noDoublesFalse,则表达式会短路到True。如果noDoublesTrue,那么len(i) != len(set(i)))只是对重复项的肮脏测试。