使用lambda验证列表中的所有元素

时间:2013-02-26 03:31:11

标签: python lambda

我有一份名为“my_foods”的食物清单。

我想使用lambda函数来验证列表“good_foods”中的所有元素是否出现在列表“my_foods”中,并且还验证列表“bad_foods”中的所有元素都不会出现在“my_foods”中。

我可以用嵌套的for循环和if语句来解决这个问题,但是如果lambdas更优雅的话我很好奇。

如果“my_foods”同时具有“apple”和“carrot”,则以下成功执行:

good_foods = ['apple', 'carrot']
junk_foods = ['soda', 'burger']

my_foods = ['banana', 'carrot', 'bread', 'apple']

result = ( filter(lambda x: x in my_foods, good_foods) and
    not filter(lambda x: x in my_foods, junk_foods) )

print result
# True

然而,如果“my_foods”只有“apple”或只有“胡萝卜”,那么下面仍然会返回True,我不希望如此。我希望它返回False。我想验证所有“good_foods”是否在列表“my_foods”中:

good_foods = ['apple', 'carrot']
junk_foods = ['soda', 'burger']

my_foods = ['banana', 'carrot', 'bread']

result = ( filter(lambda x: x in my_foods, good_foods) and
    not filter(lambda x: x in my_foods, junk_foods) )

print result
# True

另外,如果“my_foods”既没有“apple”也没有“carrot”,那么下面会返回一个空列表。我希望它返回False:

good_foods = ['apple', 'carrot']
junk_foods = ['soda', 'burger']

my_foods = ['banana', 'bread']

result = ( filter(lambda x: x in my_foods, good_foods) and
    not filter(lambda x: x in my_foods, junk_foods) )

print result
# []

最后,如果任何“bad_foods”在列表“my_foods”中,则下面成功执行并返回False,这就是我想要的实例:

good_foods = ['apple', 'carrot']
junk_foods = ['soda', 'burger']

my_foods = ['banana', 'carrot', 'bread', 'apple', 'soda']

result = ( filter(lambda x: x in my_foods, good_foods) and
    not filter(lambda x: x in my_foods, junk_foods) )

print result
# False

感谢您的帮助!

5 个答案:

答案 0 :(得分:2)

我会使用any()all()来解决这个问题:

result = (all(f in my_foods for f in good_foods) and
    not any(f in my_foods for f in junk_foods))

如果您真的想使用lambda,可以这样做:

lambda my f: f in my_foods
lambda bad f: f in junk_foods

result = all(my(f) for f in good_foods) and not any(bad(f) for f in my_foods)

但我会用真正的函数来做上面的事情:

def my(f):
    return f in my_foods

def bad(f):
    return f in junk_foods

result = all(my(f) for f in good_foods) and not any(bad(f) for f in my_foods)

现在,如果您真的想使用lambdamap() reduce()执行此操作,请接受以下建议:

result = (reduce(lambda x, y: x and y, map(lambda f: f in my_foods, good_foods))
    and reduce(lambda x, y: x and y, map(lambda f: f not in junk_foods, my_foods)))

如果我们利用内置的bool.__and__()函数来实现逻辑和布尔运算,我认为上面的内容会略有改进:

result = (reduce(bool.__and__, map(lambda f: f in my_foods, good_foods))
    and reduce(bool.__and__, map(lambda f: f not in junk_foods, my_foods)))

但如果您愿意,可以使用filter()来解决此问题。 filter()删除未通过测试的元素,因此找出每个元素是否通过测试的最简单方法是查看结果列表是否与原始列表的长度相同。

result = (len(filter(lambda f: f in my_foods, good_foods)) == len(good_foods) and
    len(filter(lambda f: f not in junk_foods, my_foods)) == len(my_foods))

请注意,any()all()都有“短路”评估;在不真正需要检查列表中的每个元素的情况下,它们将比reduce()更快。例如,如果列表中的第一项位于junk_foods列表中,则any()测试将立即完成,not any(...)将评估为Falsereduce()答案仍将通过整个junk_foods列表。

另请注意,对于大型列表,使用集合可以大大提高速度。其他一些答案建议将列表转换为集合并使用集合功能;这可能是最好的方式。

答案 1 :(得分:2)

good_foods = ['apple', 'carrot']
junk_foods = ['soda', 'burger']

my_foods = ['banana', 'carrot', 'bread', 'apple', 'soda']

result = all( map( lambda x: x in my_foods, good_foods ) ) and 
         not( any( map( lambda x: x in junk_foods, my_foods ) ) ) 

答案 2 :(得分:1)

您无法使用的任何理由:

bool(set(my_foods).difference(junk_foods).intersection(good_foods))

所以:

  • my_foods
  • 中删除所有垃圾食品
  • 确保非垃圾项目为good_foods
  • 将结果转换为布尔值,因此[]为False,任何剩下的都是True

快速,易读。

常见的情况似乎是非垃圾食品......所以我们这样做:

non_junk = set(my_foods).difference(junk_foods)

所有美味的食物都在非垃圾食品中:

set(good_foods).issubset(non_junk)

不是垃圾的好食物

non_junk.intersection(good_foods)

答案 3 :(得分:0)

解释你的描述,给出

all(food in my_foods for food in good_foods) and \
not any(food in my_foods for food in junk_foods)

如果将my_foods设为

,效率会更高
>>> good_foods = ['apple', 'carrot']
>>> junk_foods = ['soda', 'burger']
>>> my_foods = {'banana', 'carrot', 'bread', 'apple'}
>>> all(food in my_foods for food in good_foods) and \
... not any(food in my_foods for food in junk_foods)
True
>>> my_foods = {'banana', 'carrot', 'bread'}
>>> all(food in my_foods for food in good_foods) and \
... not any(food in my_foods for food in junk_foods)
False
>>> my_foods = {'banana', 'bread'}
>>> all(food in my_foods for food in good_foods) and \
... not any(food in my_foods for food in junk_foods)
False
>>> my_foods = {'banana', 'carrot', 'bread', 'apple', 'soda'}
>>> all(food in my_foods for food in good_foods) and \
... not any(food in my_foods for food in junk_foods)
False

答案 4 :(得分:0)

将所有列表转换为集合并执行:

result = my_foods >= good_foods and not my_foods & junk_foods

所以你的食物必须包含所有好食物而不包含任何垃圾食​​物

为避免处理整个junk_food集,您可以执行以下操作:

result = my_foods >= good_foods and my_foods.isdisjoint(junk_foods)