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

Dra*_*mon 96 python indexing list find

我的代码看起来像这样:

thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)
Run Code Online (Sandbox Code Playgroud)

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

我能做到这一点:

try:
    thing_index = thing_list.index(thing)
except ValueError:
    thing_index = -1
otherfunction(thing_list, thing_index)
Run Code Online (Sandbox Code Playgroud)

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

thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]
Run Code Online (Sandbox Code Playgroud)

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

Sil*_*ost 60

使用try-except子句没有任何"脏".这是pythonic的方式.ValueError.index仅通过该方法引发,因为它是您在那里唯一的代码!

回答评论:
在Python中,更容易请求宽恕而不是获得权限哲学已经建立,并且不会 index因任何其他问题而引发此类错误.不是我能想到的.

  • 当然例外情况是例外情况,这不是那个例子.如果异常比ValueError更具体,我不会遇到这样的问题. (23认同)
  • 不是`{} .get(index,'')`更pythonic?更不用说更短的可读性了. (4认同)
  • 但关键是最pythonic解决方案是使用*only*try/except而不是-1 sentinel值.IE你应该重写`otherfunction`.另一方面,如果它没有破损,...... (3认同)
  • 当我期望密钥存在时,我使用 dict[key] ;当我不确定时,我使用 dict.get(key) ,并且我*正在*在这里寻找等效的东西。返回 `None` 而不是 -1 就可以了,但是正如您自己评论的那样, str.find() 返回 -1 那么为什么不应该有 list.find() 做同样的事情呢?我不相信“Pythonic”的说法 (2认同)
  • @Andrew:说实话,它可能是第三方代码. (2认同)

Emi*_*nov 48

thing_index = thing_list.index(elem) if elem in thing_list else -1
Run Code Online (Sandbox Code Playgroud)

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

  • 简单的是,但这将进行两次线性搜索,虽然性能不是本身的问题,但这似乎过多. (24认同)
  • @Draemon:同意 - 这将做2次通过 - 但是从千行代码库这个不太可能是瓶颈.:)人们可以随时选择使用`for`进行必要的解决方案. (4认同)

Ros*_*ers 16

get类型有一个dict函数,如果字典中不存在该键,则第二个参数为list它应该返回的值.类似地,有getindexdefault,它返回get密钥存在时的值,否则它根据您的默认参数设置值,然后返回您的默认参数.

您可以扩展dict类型以获得list方法.

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

然后可以使用它,如:

mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
Run Code Online (Sandbox Code Playgroud)


Ven*_*ddy 12

如果您经常这样做,那么最好将其存放在辅助函数中:

def index_of(val, in_list):
    try:
        return in_list.index(val)
    except ValueError:
        return -1 
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记“-1”是一个有效的索引:“in_list[-1]”,尽管显然不是从“index()”返回的。可能返回“无”? (8认同)

Ala*_*iel 7

那这个呢 :

li = [1,2,3,4,5] # create list 

li = dict(zip(li,range(len(li)))) # convert List To Dict 
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None 
li.get(1)  # 0 
Run Code Online (Sandbox Code Playgroud)


Ten*_*she 6

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

相比之下,Python 一直使用异常来表示正常的程序流程,例如ValueError我们在这里讨论的引发 a 。在 Python 风格中,这并没有什么“肮脏”的地方,而且还有更多的地方。一个更常见的例子是StopIteration异常,它由迭代器的next()方法引发,以表示没有其他值。


jfs*_*jfs 5

您使用的代码没有任何问题ValueError.如果你想避免例外情况,这是另一个单线:

thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
Run Code Online (Sandbox Code Playgroud)