Python习惯用法返回唯一元素或None



我有一个列表,它可能包含也可能不包含满足给定谓词的唯一元素。我正在寻找一个表达式,如果它存在是唯一的,则计算为满足该谓词的项目,否则返回None。就像

numbers = [4, 3, 9, 7, 1, 2, 8]
print(the(item for item in numbers if item > 10))     # None
print(the(item for item in numbers if item % 2 == 0)) # None
print(the(item for item in numbers if item % 7 == 0)) # 7

是否有内置的习惯用法,或者我必须编写自己的the函数?

我不知道一个单一的表达方式,但这个简单的函数应该工作:

def the(it, cond):
    l = [ i for i in it if cond(i) ]
    return l[0] if len(l) == 1 else None
测试:

>>> print(the(numbers,(lambda x: x > 10)))
None
>>> print(the(numbers,(lambda x: x % 7 == 0)))
7
>>> print(the(numbers,(lambda x: x % 2 == 0)))
None

您可以尝试使用islice询问两个元素,这会更简单:

def the(it):
    tmp = list(islice(it, 2))
    return tmp[0] if len(tmp) == 1 else None

或循环:

def the(it):
    value = None
    for i, value in enumerate(it):
        if i == 1:
            return None
    return value

或者next的另一种用法:

def the(it):
    first = next(it, None)
    o = object()
    if next(it, o) is o:
        return first

或与你的相似:

def the(it):
    first = next(it, None)
    try:
        next(it)
    except:
        return first

为了记录,我可以只写the

def the(it):
    it = iter(it)
    try:
        value = next(it)
    except StopIteration:
        return None
    try:
        next(it)
    except StopIteration:
        return value
    return None

这个问题应该有一个简单的解决方案:

def the(items):
    return items[0] if (len(items) == 1) else None
numbers = [4, 3, 9, 7, 1, 2, 8]
print(the([item for item in numbers if item > 10]))     # None
print(the([item for item in numbers if item % 2 == 0])) # None
print(the([item for item in numbers if item % 7 == 0])) # 7

您还可以应用以下格式。从代码的角度来看,它可能不会更简单,但当项数较大时,它肯定会更快。

print(the(list(filter(lambda x: x > 10, numbers))))     # None
print(the(list(filter(lambda x: x % 2 == 0, numbers)))) # None
print(the(list(filter(lambda x: x % 7 == 0, numbers)))) # 7

您可以使用以下惰性方法。从生成器表达式中获取下两项,如果来自生成器的第二项不是None,则返回None:

def func(lst, pred):
    gen = (i for i in lst if pred(i))
    v, w = next(gen, None), next(gen, None)
    return v if w is None else None

print(func([4, 3, 9, 7, 1, 2, 8], lambda x: x>10))
# None
print(func([4, 3, 9, 7, 1, 2, 8], lambda x: x % 2 == 0))
# None
print(func([4, 3, 9, 7, 1, 2, 8], lambda x: x % 7 == 0))
# 7
print(func([4, 3, 9, 0, 1, 2, 8], lambda x: x % 7 == 0))
# 0

最新更新