在元组或对象列表上使用Python的list index()方法?

72 投票
13 回答
233738 浏览
提问于 2025-04-15 12:01

Python的列表类型有一个叫做index()的方法,它需要一个参数,然后返回列表中第一个与这个参数匹配的项的索引(位置)。比如说:

>>> some_list = ["apple", "pear", "banana", "grape"]
>>> some_list.index("pear")
1
>>> some_list.index("grape")
3

有没有一种优雅(符合习惯)的方式,可以把这个方法扩展到复杂对象的列表,比如元组?理想情况下,我想能做这样的事情:

>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> some_list.getIndexOfTuple(1, 7)
1
>>> some_list.getIndexOfTuple(0, "kumquat")
2

getIndexOfTuple()只是一个假设的方法,它接受一个子索引和一个值,然后返回列表中在那个子索引位置上有给定值的项的索引。我希望

有没有什么方法可以实现这个通用的结果,使用列表推导式或者lambda函数,或者其他类似的“内联”方式?我觉得我可以自己写一个类和方法,但如果Python已经有现成的办法,我就不想重复造轮子。

13 个回答

11

一种方法是使用来自 operator 模块的 itemgetter 函数:

import operator

f = operator.itemgetter(0)
print map(f, tuple_list).index("cherry") # yields 1

调用 itemgetter 会返回一个函数,这个函数可以对传给它的任何东西执行类似于 foo[0] 的操作。然后,使用 map,你可以将这个函数应用到每一个元组上,从而提取信息到一个新的列表中,接着你可以像往常一样在这个新列表上调用 index

map(f, tuple_list)

这相当于:

[f(tuple_list[0]), f(tuple_list[1]), ...etc]

而这又相当于:

[tuple_list[0][0], tuple_list[1][0], tuple_list[2][0]]

最终得到:

["pineapple", "cherry", ...etc]
30

那些列表推导式用久了就会变得很乱。

我喜欢这种更符合Python风格的方法:

from operator import itemgetter

tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]

def collect(l, index):
   return map(itemgetter(index), l)

# And now you can write this:
collect(tuple_list,0).index("cherry")   # = 1
collect(tuple_list,1).index("3")        # = 2

如果你需要你的代码运行得非常快:

# Stops iterating through the list as soon as it finds the value
def getIndexOfTuple(l, index, value):
    for pos,t in enumerate(l):
        if t[index] == value:
            return pos

    # Matches behavior of list.index
    raise ValueError("list.index(x): x not in list")

getIndexOfTuple(tuple_list, 0, "cherry")   # = 1
83

这个怎么样?

>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> [x for x, y in enumerate(tuple_list) if y[1] == 7]
[1]
>>> [x for x, y in enumerate(tuple_list) if y[0] == 'kumquat']
[2]

正如评论中提到的,这样做会得到所有匹配的结果。如果只想要第一个匹配的结果,可以这样做:

>>> [y[0] for y in tuple_list].index('kumquat')
2

评论中有个不错的讨论,讲的是不同解决方案之间的速度差异。我可能有点偏见,但我个人觉得用一行代码就可以解决这个问题,因为我们讨论的速度差异其实很小,不值得为了这个问题去创建函数或导入模块。不过,如果你打算处理大量元素,可能需要看看其他的答案,因为它们的速度比我提供的要快。

撰写回答