1

我有一份名为“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”或只有“carrot”,那么下面仍然返回 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

谢谢你的帮助!

4

5 回答 5

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)

现在,如果您真的想lambda使用map()or来做到这一点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

另请注意,对于大型列表,您将通过使用集合获得很大的速度提升。其他一些答案建议将列表转换为集合并使用集合功能;这可能是最好的方法。

于 2013-02-26T03:47:45.903 回答
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 ) ) ) 
于 2013-02-26T03:49:41.207 回答
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)
于 2013-02-26T03:37:41.623 回答
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
于 2013-02-26T03:52:49.827 回答
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)
于 2013-02-26T03:58:47.430 回答