繁体   English   中英

在Python中,如何检查项目列表是否是一个列表中的一个列表?

[英]In Python, how to you check to see if a list of items is exclusive to one list out of two?

我有两个包含互斥物品的清单 - 我们为这些清单选择油和水基液体,因为这些自然不能混合:

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

我想测试foo是否只包含水列表或油类列表中的项目,但不包括两者。 这样:

foo = ['tea', 'corn oil'] => FAIL
bar = ['pepsi', 'tea', 'juice'] => PASS
baz = ['olive oil'] => PASS

到目前为止我的尝试:

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

不用说它很难看但有效吗? 我怎么能做得更好?

将所有内容定义为集合(或将它们转换为集合),然后是简单的set / bitwise操作:

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

快速单行可能看起来像:

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运算符将在恒定时间内工作。 如果你不能创建输入集,那么你可以写:

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

如果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'])

还有一个测试组

foo = frozenset(['tea', 'corn oil'])

您可以通过检查集合是否不相交来确定集合是否仅包含来自一个组的项目(使用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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM