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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18533620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:57:54  来源:igfitidea点击:

Getting the first non None value from list

pythonlist

提问by Pran

Given a list, is there a way to get the first non-None value? And, if so, what would be the pythonic way to do so?

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

For example, I have:

例如,我有:

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

In this case, if a is None, then I would like to get b. If a and b are both None, the I would like to get d.

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

Currently I am doing something along the lines of (((a or b) or c) or d), is there another way?

目前我正在做一些类似的事情(((a or b) or c) or d),还有其他方法吗?

采纳答案by alecxe

You can use next():

您可以使用next()

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

If the list contains only Nones, it will throw StopIterationexception. If you want to have a default value in this case, do this:

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

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

回答by Jon Clements

Adapt from the following (you could one-liner it if you wanted):

改编自以下内容(如果你愿意,你可以单行它):

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

This takes the first non Nonevalue, or returns Noneinstead.

这需要第一个非None值,或者返回None

回答by pylang

first_trueis an itertoolsrecipe found in the Python 3 docs:

first_trueitertoolsPython 3 文档中找到的配方:

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)

One may choose to implement the latter recipe or import more_itertools, a library that ships with itertoolsrecipes and more:

可以选择实现后一个 recipe 或 import more_itertools,一个带有itertools配方等的库:

> pip install more_itertools

Use:

用:

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'


Why use the predicate?

为什么要使用谓词?

"First non-None" item is not the same as "first True" item, e.g. [None, None, 0]where 0is the first non-None, but it is not the first Trueitem. The predicate allows first_trueto be useable, ensuring any first seen, non-None, falsey item in the iterable is still returned (e.g. 0, False) instead of the default.

“第一个非None”项目与“第一个True”项目不同,例如第一个非项目[None, None, 0]在哪里,但它不是第一个项目。谓词允许是可用的,确保迭代中的任何第一次看到的、非无的、虚假的项目仍然返回(例如,)而不是默认值。0NoneTruefirst_true0False

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

回答by DannyMoshe

I think this is the simplest waywhen dealing with a small set of values (will work in a list comprehension as well):

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

firstVal = a or b or c or d

Will always return the first non "False" value which works in some cases (given you dont expect any values which could evaluate to false as @GrannyAching points out below)

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

回答by Lars Blumberg

When the items in your list are expensive to calculate such as in

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

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)

then you might want to avoid the repetitive calculation and simplify to:

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

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)