在python中处理list.index(可能不存在)的最佳方法?

我的代码看起来像这样:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)

好的,这样简化但你明白了。 现在ValueError可能实际上不在列表中,在这种情况下我想传递-1为thing_index。在其他语言中,如果找不到元素,这是你期望返回的index()。 事实上,它抛出ValueError。

我能做到这一点:

try:

thing_index = thing_list.index(thing)
except ValueError:
thing_index = -1
otherfunction(thing_list, thing_index)

但这感觉很脏,而且我不知道ValueError是否可能因为其他原因而被提出。 我想出了基于生成器函数的以下解决方案,但它看起来有点复杂:

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]

是否有更清洁的方法来实现同样的目标? 我们假设列表没有排序。

10个解决方案

50 votes

使用try-except子句没有任何“脏”。 这是pythonic的方式。 index将仅由.index方法提出,因为它是您在那里唯一的代码!

回答评论:

在Python中,更容易请求宽恕而不是获得许可哲学已经确立,并且没有index不会针对任何其他问题引发此类错误。 不是我能想到的。

SilentGhost answered 2019-04-22T02:13:10Z
37 votes
thing_index = thing_list.index(elem) if elem in thing_list else -1

一条线。 简单。 没有例外。

Emil Ivanov answered 2019-04-22T02:13:36Z
14 votes

list类型具有list函数,其中如果字典中不存在该键,则list的第二个参数是它应返回的值。 类似地,有list,如果密钥存在,则返回getindexdefault中的值,否则根据默认参数设置值,然后返回默认参数。

您可以将list类型扩展为getindexdefault方法。

class SuperDuperList(list):
def getindexdefault(self, elem, default):
try:
thing_index = self.index(elem)
return thing_index
except ValueError:
return default

然后可以使用它,如:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
Ross Rogers answered 2019-04-22T02:14:16Z
5 votes

您的代码使用ValueError没有任何问题。如果您想避免异常,这是另一个单行程序:

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
jfs answered 2019-04-22T02:14:46Z
3 votes

这个问题是语言哲学之一。 例如,在Java中,一直存在一种传统,即异常应该仅用于发生错误的“异常情况”,而不是流量控制。 起初这是出于性能原因,因为Java异常很慢,但现在这已成为公认的风格。

相比之下,Python总是使用异常来指示正常的程序流程,就像我们在这里讨论的那样提出StopIteration。 在Python风格中没有任何“脏”的东西,还有更多来自它的地方。 一个更常见的例子是StopIteration异常,它由迭代器的next()方法引发,表示没有其他值。

Tendayi Mawushe answered 2019-04-22T02:15:23Z
1 votes

那这个呢:

otherfunction(thing_collection, thing)

而不是像函数接口中的列表索引那样公开依赖于实现的东西,传递集合和东西,让其他函数处理“测试成员资格”问题。 如果其他函数被编写为集合类型不可知,那么它可能会从以下开始:

if thing in thing_collection:
... proceed with operation on thing

如果thing_collection是list,tuple,set或dict,它将起作用。

这可能比:

if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:

这是你在其他功能中已有的代码。

PaulMcG answered 2019-04-22T02:16:16Z
0 votes

我对列表中的“.index()”方法也有同样的问题。 我没有问题它会引发异常,但我强烈不同意这是一个非描述性的ValueError这一事实。 但我可以理解它是否会是一个IndexError。

我可以看到为什么返回“-1”也是一个问题因为它是Python中的有效索引。 但实际上,我从不期望“.index()”方法返回负数。

这里是一个班轮(好吧,这是一个相当长的行...),只列出一次列表,如果找不到该项,则返回“无”。 如果您愿意,重写它以返回-1将是微不足道的。

indexOf = lambda list, thing: \
reduce(lambda acc, (idx, elem): \
idx if (acc is None) and elem == thing else acc, list, None)

如何使用:

>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>
haavee answered 2019-04-22T02:17:00Z
0 votes

如果你经常这样做,那么最好把它放在辅助函数中:

def index_of(val, in_list):
try:
return in_list.index(val)
except ValueError:
return -1
Veneet Reddy answered 2019-04-22T02:17:28Z
-2 votes

我不知道你为什么认为它很脏...因为例外? 如果你想要一个oneliner,这里是:

thing_index = thing_list.index(elem) if thing_list.count(elem) else -1

但我建议不要使用它; 我认为Ross Rogers解决方案是最好的,使用一个对象来封装你的desiderd行为,不要试图以可读性为代价将语言推到极限。

Alan Franzoni answered 2019-04-22T02:18:04Z
-2 votes

我建议:

if thing in thing_list:
list_index = -1
else:
list_index = thing_list.index(thing)
Jonas answered 2019-04-22T02:18:32Z