如何获取python列表的第n个元素或默认值(如果不可用)


143

我在寻找dictionary.get(key, default)for清单的python中的等效项。是否有一个线性惯用法来获取列表的第n个元素或默认值(如果不可用)?

例如,给定一个列表myList我想要得到myList[0],如果myList为空列表则为5 。

谢谢。

Answers:


123
l[index] if index < len(l) else default

为了支持负索引,我们可以使用:

l[index] if -len(l) <= index < len(l) else default

3
但是,如果您的列表没有名称,则无法使用-例如,在列表理解中。
熊加亚莫夫2011年

9
您似乎忘记了负索引的情况。例如。index == -1000000应该回来default
nodakai 2012年

3
@nodakai,很好。有时我为此而被咬。x[index] if 0 <= index < len(x) else default如果index可以是负面的,那会更好。
Ben Hoyt

3
@nodakai哇-这是一个很好的例子,为什么使用try / except可能比尝试正确地对测试进行编码以使它永远不会失败更好。我仍然不愿意依赖try / except,因为我知道会发生这种情况,但这增加了我考虑的意愿。
ToolmakerSteve

6
@ToolmakerSteve:您的公式valid_index()不正确。负索引在Python中合法的-应该是-len(l) <= index < len(l)
Tim Pietzcker 2014年

57
try:
   a = b[n]
except IndexError:
   a = default

编辑:我删除了对TypeError的检查-可能最好让调用者处理。


3
我喜欢这个。只需将其包装在函数周围,以便您可以使用iterable作为参数来调用它。更容易阅读。
Noufal Ibrahim

35
(a[n:]+[default])[0]

a越大越好

(a[n:n+1]+[default])[0]

这是可行的,因为if a[n:]是一个空列表,ifn => len(a)

这是一个如何与 range(5)

>>> range(5)[3:4]
[3]
>>> range(5)[4:5]
[4]
>>> range(5)[5:6]
[]
>>> range(5)[6:7]
[]

和完整的表达

>>> (range(5)[3:4]+[999])[0]
3
>>> (range(5)[4:5]+[999])[0]
4
>>> (range(5)[5:6]+[999])[0]
999
>>> (range(5)[6:7]+[999])[0]
999

5
您会在没有注释的情况下以实际代码编写此代码吗?
彼得·汉森

1
@Peter Hansen,仅当我打高尔夫球时才可用;)但是,它确实适用于所有版本的Python。接受的答案仅适用于2.5+版本
John La Rooy

3
它邀请创建3个临时列表并访问2个索引以选择一个项目。
Joachim Jablon 2014年

尽管我永远不会在“真实”代码中执行此操作,但这是一个很好的简洁代码,我可以在python REPL中轻松使用,因此您大为赞赏。
Cookyt '17

next(iter(lst[i:i+1]), default)-这只是神秘的丑陋单线比赛中的另一项参赛作品。
jfs

28

刚刚发现:

next(iter(myList), 5)

iter(l)在上返回迭代器myListnext()消耗迭代器的第一个元素,并引发StopIteration错误,除非使用默认值调用(在这种情况下为第二个参数,5

这仅在您需要第一个元素时才有效,在您的示例中就是这种情况,但在您要提问的文本中不是如此,所以...

此外,它不需要在内存中创建临时列表,并且即使没有名称,它也可以用于任何可迭代的类型(请参阅Xiong Chiamiov对gruszczy答案的评论)


3
结合其他答案: next(iter(myList[n:n+1]), 5) 现在,它适用于nth元素。
Alfe

这不适用于非列表。此时,try:except-ing IndexError读起来像个更好的主意恕我直言。此外,它还会在内存中创建一个列表。
约阿希姆·贾布隆

try变体不是单线的(OP要求)。它仅适用于列表,因为它myList是由OP指定的列表(准确地说,它是可索引的)。在内存中创建副本的成本并不高,因为我在此处创建一个(或无)单个元素的列表。当然,有一些开销,但是除非您在循环中进行数百万次,否则不值得一提。顺便说一句,我想创建和捕获IndexError异常可能会更昂贵。
Alfe

可读性很重要:)如果您正要提高IndexError的成本,那么也许您应该使用Python来完成整个工作。
约阿希姆·贾布隆

20
(L[n:n+1] or [somedefault])[0]

1
+1,因为这使我得以了解所做的[] or ...事情。但是,我个人只会使用公认的解决方案,因为它易于阅读(对于新手)。当然,将其包装在带有注释的“ def”中将使大部分问题不再存在。
制造商史蒂夫(Steve)2013年

如果L[n] == False或者L[n] == None或者L[n] == []更全局地将所有评估为False的东西怎么办?
Joachim Jablon 2014年

@JoachimJablon:仍然有效。切片返回一个列表,并且[False]为true。
伊格纳西奥·巴斯克斯

哦,确实没有意识到清单已被检查,而不是价值。
Joachim Jablon 2014年

你为什么把它包裹在一个元组中?我认为myval = l[n:n+1] or [somedefault]会很好吗?
Rotareti

8

...在dict.get(key, default)for列表中寻找python中的等效项

有一个itertools配方可用于常规可迭代对象。为了方便起见,您可以> pip install more_itertools导入此为您实现此类配方的第三方库:

import more_itertools as mit


mit.nth([1, 2, 3], 0)
# 1    

mit.nth([], 0, 5)
# 5    

详情

这是nth配方的实现:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(itertools.islice(iterable, n, None), default)

像一样dict.get(),此工具返回缺失索引的默认值。它适用于一般可迭代项:

mit.nth((0, 1, 2), 1)                                      # tuple
# 1

mit.nth(range(3), 1)                                       # range generator (py3)
# 1

mit.nth(iter([0, 1, 2]), 1)                                # list iterator 
# 1  

2

一种便宜的解决方案是.get()像往常一样使用枚举和用法来真正做出命令。

 dict(enumerate(l)).get(7, my_default)

1

将@Joachim与上述内容结合使用,您可以使用

next(iter(my_list[index:]), default)

例子:

next(iter(range(10)[8:]), 11)
8
>>> next(iter(range(10)[12:]), 11)
11

或者,也许更清楚,但是没有 len

my_list[index] if my_list[index:] else default

1

使用Python 3.4 contextlib.suppress(exceptions)构建getitem()类似于的方法getattr()

import contextlib

def getitem(iterable, index, default=None):
    """Return iterable[index] or default if IndexError is raised."""
    with contextlib.suppress(IndexError):
        return iterable[index]
    return default
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.