Python:用于测试列表中任何条件的通用迭代器或纯函数

时间:2016-11-23 06:35:30

标签: python lambda iterator

我希望有一个函数AllTrue,它有三个参数:

  • 列表:值列表
  • 功能:应用于所有值的功能
  • 条件:根据功能的输出进行测试

并返回列表中所有值是否与条件匹配的布尔值。

我可以按照以下方式将其用于基本条件:

def AllTrue(List, Function = "Boolean", Condition = True):
  flag = True
  condition = Condition
  if Function == "Boolean"
    for element in List:
      if element != condition:
        flag = False
        break
  else:
    Map = map(Function, List)
    for m in Map:
      if m != condition:
        flag = False
        break
  return flag

因为如果某些东西是真的,python没有明确返回的函数,我只是制作默认的"布尔"。可以通过定义TrueQ来清除这一点,如果元素为True则返回True,然后只在TrueQ上映射List

else处理如下的查询:

l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
AllTrue(l, len, 2)
#False

测试列表中的所有元素是否长度为2.但是,它无法处理更复杂的条件,如> / <或复合条件,如len > 2 and element[0] == 15

怎么能这样做?

清理版本

def TrueQ(item):
  return item == True


def AllTrue(List, Function = TrueQ, Condition = True):
  flag = True
  condition = Condition
  Map = map(Function, List)
  for m in Map:
    if m != condition:
      flag = False
      break
  return flag

然后只需致电AllTrue(List,TrueQ)

3 个答案:

答案 0 :(得分:0)

Python已经内置了您正在尝试构建的机制。例如,检查列表中的所有数字是否均匀,代码可以是:

if all(x%2==0 for x in L):
    ...

如果你想检查所有值都是“真实的”,那么代码就更简单了:

if all(L):
    ...

请注意,在第一个版本中,代码也会“短路”,换句话说,只要结果已知,评估就会停止。在:

if all(price(x) > 100 for x in stocks):
    ...

在找到价格较低或相等的第一个股票之前,将调用函数价格。此时搜索将停止,因为结果已知为False

要检查列表2中的所有长度均为L,代码就是:

if all(len(x) == 2 for x in L):
    ...

即。或多或少是请求的字面翻译。无需为此编写函数。

如果此类测试是您希望作为参数传递给另一个函数的“过滤器”,那么lambda可能会变得有用:

def search_DB(test):
    for record in database:
        if test(record):
            result.append(record)
            ...

search_DB(lambda rec: all(len(x) == 2 for x in rec.strings))
  

我想要一个带有列表,函数和条件的函数,并告诉我列表中的每个元素是否与条件匹配。即foo(List,Len,&gt; 2)

在Python中>2写成lambda x : x>2

(遗憾的是)Python中没有元编程工具允许只编写>2或类似·>2的内容,除非使用eval的字符串文字评估而你不想要要做到这一点。甚至标准的Python库都尝试沿着这条路走下去(参见namedtuple中的collections实现),但这真的很难看。

我不是说写>2会是一个好主意,但如果这是一个好主意,有办法做到这一点会很好。不幸的是,为了获得不错的元编程能力,你需要一种表示代码作为数据的同源语言,因此你将使用Lisp或其他元语言进行编程,而不是Python(在Lisp中编程确实是一个好主意,但出于我不知道的原因,这种方法仍然不受欢迎)。

鉴于此,函数foo将被调用为

foo(L, len, lambda x : x > 2)

只是

def foo(L, f=lambda x : x, condition=lambda x: x):
    return all(condition(f(x)) for x in L)

但没有Python程序员会编写这样的函数,因为对foo的原始调用实际上更多代码不太清晰比使用以下内容进行内联: / p>

all(len(x) > 2 for x in L)

并要求你也要了解这个事情foo(做all和生成器表达式会做什么,只是更慢,代码更多,更混淆)。

答案 1 :(得分:0)

你正在重新发明轮子。只需使用这样的东西:

>>> l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
>>> def all_true(iterable, f, condition):
...     return all(condition(f(e)) for e in iterable)
... 
>>> def cond(x): return x == 2
... 
>>> all_true(l, len, cond)
False

您可以定义不同的功能来检查不同的条件:

>>> def cond(x): return x >=  1
... 
>>> all_true(l, len, b)
True
>>> 

而且,实际上,拥有自己的功能似乎有点矫枉过正。例如,处理你的复杂情况&#34;你可以简单地做一些事情:

>>> l = [[0,2],[0,1,2],[0,1,3,4]]
>>> all(len(sub) > 2 and sub[0] == 5 for sub in l)
False
>>> all(len(sub) > 1 and sub[0] == 0 for sub in l)
True
>>> 

答案 2 :(得分:0)

我认为在这种情况下理想的解决方案可能是:

Content-Length

因此允许复杂的查询,如:

def AllTrue(List, Test = lambda x:x):
  all(Test(x) for x in List) 

要遵守Juanpa的建议,这里是python命名约定和我现在在问题中发布的扩展,能够处理像x&gt;这样的简单条件。值。

l = [[0, 1], [1, 2, 3], [2, 5]]

AllTrue(l, lambda x: len(x) > 2 and x[0] == 1)

注意:这适用于单一条件,但不适用于复杂条件,如

from operator import * all_true(a_list, a_function, an_operator, a_value): a_map = map(a_function, a_list) return all( an_operator(m, a_value) for m in a_map) l = [[0,2],[0,1,2],[0,1,3,4]] all_true(l, len, gt, 2) #True