在Python中,如何检查一个项列表是否只包含两个列表中的一个?

2024-10-01 09:20:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个列表,其中包含相互排斥的项目-让我们为这些列表选择油基和水基液体,因为它们自然不能混合:

waters = ['tea', 'lemonade', 'juice', 'pepsi']
oils = ['olive oil', 'corn oil', 'peanut oil']

我想测试一下foo是否只包含水列表或油列表中的项目,而不是两者都包含。因此:

^{pr2}$

我目前的尝试:

def contains_conflicting_types(test, targets, conflicts):
    intarget = False
    inconflict = False
    for t in test:
        if t in targets:
            intarget = True
        if t in conflicts:
            inconflict = True
        if intarget and inconflict:
            return True
    return False

#Usage:
contains_conflicting_types(['A','B'], ['A','1'], ['B','2']) #returns True A and B are in conflict

不用说它很难看但很管用?我怎样才能做得更好?在


Tags: 项目intestfalsetrue列表iftypes
3条回答

一句简短的话可能看起来像:

def contains_conflicting_types(test, targets, conflicts):
    return not(all(t in targets for t in test) or all(t in conflicts for t in test))

如果设置了targetsconflicts,这会更快,因为在这种情况下,in运算符将在恒定时间内工作。如果无法设置输入集,则可以编写:

^{pr2}$

如果test也是一个集,那么可以利用重载的<=运算符进行子集检查并写入:

def contains_conflicting_types(test, targets, conflicts):
    return not (test <= targets or test <= conflicts)

给出两组比较的结果

waters = frozenset(['tea', 'lemonade', 'juice', 'pepsi'])
oils = frozenset(['olive oil', 'corn oil', 'peanut oil'])

和一个测试组

^{pr2}$

通过检查集合是否是disjoint(如果两个集合的交集为空集,则两个集合是不相交的)来确定集合是否只包含一个组中的项目(使用XOR运算符)。在

foo.isdisjoint(waters) ^ foo.isdisjoint(oils)

对于Python 2.5及更高版本,请使用:

bool(foo.intersection(waters)) ^ bool(foo.intersection(oils))

或者,如果您记得&是作用于两个集合时的交集运算符。因为可读性很重要,如果您或其他正在(或将要)维护您的代码的人不知道&字符的含义而不查找它,只需使用s1.intersection(s2)。在

bool(foo & waters) ^ bool(foo & oils)

将所有内容定义为集合(或将其转换为集合),然后就可以直接执行集合/位操作:

bool(oils & foo) ^ bool(waters & foo)
Out[19]: False

bool(oils & bar) ^ bool(waters & bar)
Out[20]: True

bool(oils & baz) ^ bool(waters & baz)
Out[21]: True

相关问题 更多 >