从列表中获取第一个非None值

Pra*_*ran 50 python list

给定一个列表,有没有办法获得第一个非None值?而且,如果是这样,那么这样做的pythonic方式是什么?

例如,我有:

  • a = objA.addreses.country.code
  • b = objB.country.code
  • c = None
  • d = 'CA'

在这种情况下,如果a是None,那么我想得到b.如果a和b都是None,我想得到d.

目前我正在做一些事情(((a or b) or c) or d),有另一种方式吗?

ale*_*cxe 96

你可以使用next():

>>> a = [None, None, None, 1, 2, 3, 4, 5]
>>> next(item for item in a if item is not None)
1
Run Code Online (Sandbox Code Playgroud)

如果列表只包含Nones,则会抛出StopIteration异常.如果您想在这种情况下使用默认值,请执行以下操作:

>>> a = [None, None, None]
>>> next((item for item in a if item is not None), 'All are Nones')
All are Nones
Run Code Online (Sandbox Code Playgroud)

  • 我添加一个`try:``除了StopIteration:`来处理只包含None项的列表.但这是一个很好的答案. (4认同)
  • @ kevlar1818,如果你省略"不是无",那么它对待0和""就像对待一个无(至少在我的python版本中) (3认同)

Dan*_*she 15

我认为这是处理一小组值时最简单的方法(也适用于列表理解):

firstVal = a or b or c or d
Run Code Online (Sandbox Code Playgroud)

将始终返回在某些情况下有效的第一个非“假”值(假设您不期望任何值可能评估为假,正如@GrannyAching 在下面指出的那样)

  • 如果有任何评估为 False 的值,则不会,例如:0、''、[]、()、False (4认同)

pyl*_*ang 8

first_truePython 3文档中itertools配方:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)
Run Code Online (Sandbox Code Playgroud)

人们可以选择实施后者的配方或导入more_itertools,附带itertools配方的库以及更多:

> pip install more_itertools
Run Code Online (Sandbox Code Playgroud)

使用:

import more_itertools as mit

a = [None, None, None, 1, 2, 3, 4, 5]
mit.first_true(a, pred=lambda x: x is not None)
# 1

a = [None, None, None]
mit.first_true(a, default="All are None", pred=lambda x: x is not None)
# 'All are None'
Run Code Online (Sandbox Code Playgroud)

为什么要使用谓词?

"第一非None"项目与"第一True"项目不同,例如[None, None, 0],0第一项是非None第一True项,但不是第一项.谓词可以first_true是可用的,确保在任何可迭代第一次看到,非无,falsey项目仍会返回(例如0,False)而不是默认的.

a = [None, None, None, False]
mit.first_true(a, default="All are None", pred=lambda x: x is not None)
# 'False'
Run Code Online (Sandbox Code Playgroud)


Lar*_*erg 7

当列表中的项目计算成本很高时,例如

first_non_null = next((calculate(x) for x in my_list if calculate(x)), None)

# or, when receiving possibly None-values from a dictionary for each list item:

first_non_null = next((my_dict[x] for x in my_list if my_dict.get(x)), None)
Run Code Online (Sandbox Code Playgroud)

那么您可能希望避免重复计算并简化为:

first_non_null = next(filter(bool, map(calculate, my_list)), None)

# or:

first_non_null = next(filter(bool, map(my_dict.get, my_list)), None)
Run Code Online (Sandbox Code Playgroud)

由于使用了生成器表达式,计算只对第一项执行,直到生成真值。


Jon*_*nts 5

从以下内容进行改编(如果需要,可以单排):

values = (a, b, c, d)
not_None = (el for el in values if el is not None)
value = next(not_None, None)
Run Code Online (Sandbox Code Playgroud)

这采用第一个非None值,或者返回None