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

时间:2013-08-30 13:04:11

标签: 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)的方式做一些事情,还有另一种方法吗?

5 个答案:

答案 0 :(得分:85)

您可以使用next()

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

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

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

答案 1 :(得分:6)

first_true是在Python 3 docs中找到的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)

可以选择实施后一个食谱或导入more_itertools,这是一个附带itertools食谱等的库:

> pip install more_itertools

使用:

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'

为什么要使用谓词?

"首先是非None" item与"第一个True"不同项目,例如[None, None, 0]其中0是第一个非None,但它不是第一个True项。谓词允许first_true可用,确保仍然返回迭代中的任何第一个看到的,非None,falsey项(例如0False)而不是默认值。

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

答案 2 :(得分:5)

从以下内容进行调整(如果需要,可以单行):

values = (a, b, c, d)
not_None = (el for el in values if el is not None)
value = next(not_None, None)

这会获取第一个非None值,或者返回None

答案 3 :(得分:1)

我认为这是处理少量值时的最简单的方法(同样适用于列表理解):

firstVal = a or b or c or d

将始终返回第一个非“ None”值

答案 4 :(得分:0)

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

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)

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

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

# or:

first_non_null = next(filter(bool, (my_dict.get(x) for x in my_list)), None)