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

Using Python's list index() method on a list of tuples or objects?

python的list类型有一个index()方法,该方法接受一个参数,并返回与该参数匹配的列表中第一个项的索引。例如:

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

是否有一种优雅的(惯用的)方法将其扩展到复杂对象列表,如元组?理想情况下,我希望能够这样做:

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

getindexofuple()只是一个假设方法,它接受一个子索引和一个值,然后用该子索引处的给定值返回列表项的索引。我希望

有没有什么方法可以达到这个一般的结果,使用列表理解或者lamba或者类似的"in-line"之类的东西?我认为我可以编写自己的类和方法,但是如果Python已经有了方法,我不想重新发明轮子。


这个怎么样?

1
2
3
4
5
>>> 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]

正如评论中指出的,这将得到所有匹配项。要获得第一个,您可以执行以下操作:

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

在评论中有一个很好的讨论,关于所有发布的解决方案之间的速度差异。我可能有点偏颇,但我个人会坚持一句话,因为我们讨论的速度相对于为这个问题创建函数和导入模块来说是微不足道的,但是如果您计划对大量元素执行此操作,那么您可能需要查看提供的其他答案,因为它们比我提供的更快。提供。


过了一会儿,这些清单的理解就乱七八糟了。

我喜欢这种方法:

1
2
3
4
5
6
7
8
from operator import itemgetter

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

如果您需要您的代码都是高性能的:

1
2
3
4
5
6
7
8
9
10
# 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


一种可能是使用来自operator模块的itemgetter函数:

1
2
3
4
import operator

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

itemgetter的调用返回一个函数,该函数将对传递给它的任何内容执行等同于foo[0]的操作。使用map,然后将该函数应用于每个元组,将信息提取到一个新列表中,然后在该列表上正常调用index

1
map(f, tuple_list)

相当于:

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

依次相当于:

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

它给出:

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


您可以通过列表理解和索引()来完成此操作。

1
2
3
4
5
tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
[x[0] for x in tuple_list].index("kumquat")
2
[x[1] for x in tuple_list].index(7)
1

受这个问题的启发,我发现这个相当优雅:

1
2
3
4
5
>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> next(i for i, t in enumerate(tuple_list) if t[1] == 7)
1
>>> next(i for i, t in enumerate(tuple_list) if t[0] =="kumquat")
2

我将此作为对Triptych的评论,但由于缺乏评级,我还无法评论:

使用枚举器方法匹配元组列表中的子索引。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
li = [(1,2,3,4), (11,22,33,44), (111,222,333,444), ('a','b','c','d'),
        ('aa','bb','cc','dd'), ('aaa','bbb','ccc','ddd')]

# want pos of item having [22,44] in positions 1 and 3:

def getIndexOfTupleWithIndices(li, indices, vals):

    # if index is a tuple of subindices to match against:
    for pos,k in enumerate(li):
        match = True
        for i in indices:
            if k[i] != vals[i]:
                match = False
                break;
        if (match):
            return pos

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

idx = [1,3]
vals = [22,44]
print getIndexOfTupleWithIndices(li,idx,vals)    # = 1
idx = [0,1]
vals = ['a','b']
print getIndexOfTupleWithIndices(li,idx,vals)    # = 3
idx = [2,1]
vals = ['cc','bb']
print getIndexOfTupleWithIndices(li,idx,vals)    # = 4


1
2
3
4
5
6
7
8
9
10
11
12
13
14
tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]

def eachtuple(tupple, pos1, val):
    for e in tupple:
        if e == val:
            return True

for e in tuple_list:
    if eachtuple(e, 1, 7) is True:
        print tuple_list.index(e)

for e in tuple_list:
    if eachtuple(e, 0,"kumquat") is True:
        print tuple_list.index(e)

好吧,这可能是vals(j)中的错误,更正如下:

1
2
3
4
5
6
7
8
9
def getIndex(li,indices,vals):
for pos,k in enumerate(lista):
    match = True
    for i in indices:
        if k[i] != vals[indices.index(i)]:
            match = False
            break
    if(match):
        return pos

我想以下不是最好的方法(速度和优雅问题),但它可以帮助:

1
2
3
4
5
6
7
8
9
from collections import OrderedDict as od
t = [('pineapple', 5), ('cherry', 7), ('kumquat', 3), ('plum', 11)]
list(od(t).keys()).index('kumquat')
2
list(od(t).values()).index(7)
7
# bonus :
od(t)['kumquat']
3

具有2个成员的元组列表可以直接转换为有序dict,数据结构实际上是相同的,所以我们可以使用dict方法。


python的list.index(x)返回列表中第一个出现的x的索引。所以我们可以通过列表压缩返回的对象来获取它们的索引。

1
2
3
4
5
>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> [tuple_list.index(t) for t in tuple_list if t[1] == 7]
[1]
>>> [tuple_list.index(t) for t in tuple_list if t[0] == 'kumquat']
[2]

在同一行中,如果有多个匹配的元素,我们也可以得到索引列表。

1
2
3
>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11), ("banana", 7)]
>>> [tuple_list.index(t) for t in tuple_list if t[1] == 7]
[1, 4]


没有人建议吃羊羔肉?

你试试这个就行了。我来找这个帖子的答案。我不觉得我喜欢,但我觉得有种感觉:p

1
2
3
    l #[['rana', 1, 1], ['pato', 1, 1], ['perro', 1, 1]]

    map(lambda x:x[0], l).index("pato") #1

编辑以添加示例:

1
   l=[['rana', 1, 1], ['pato', 2, 1], ['perro', 1, 1], ['pato', 2, 2], ['pato', 2, 2]]

按条件提取所有项:过滤器(lambda x:x[0]="pato",l)["pato",2,1],["pato",2,2],["pato",2,2]]

按条件提取所有项,索引为:

1
2
3
4
    >>> filter(lambda x:x[1][0]=="pato", enumerate(l))
    [(1, ['pato', 2, 1]), (3, ['pato', 2, 2]), (4, ['pato', 2, 2])]
    >>> map(lambda x:x[1],_)
    [['pato', 2, 1], ['pato', 2, 2], ['pato', 2, 2]]

注:u变量仅在交互式解释器y普通文本文件中工作u需要解释性赋值,即u=filter(lambda x:x[1][0]="pato",enumerate(l))。


1
2
z = list(zip(*tuple_list))
z[1][z[0].index('persimon')]