web-dev-qa-db-ja.com

タプルまたはオブジェクトのリストでPythonのリストindex()メソッドを使用していますか?

Pythonのリストタイプには、1つのパラメーターを取り、パラメーターに一致するリスト内の最初のアイテムのインデックスを返す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()は、サブインデックスと値を受け取り、そのサブインデックスで指定された値を持つリストアイテムのインデックスを返す単なる仮想メソッドです。私は願います

リストの内包表記やランバス、またはそのような「インライン」を使用して、その一般的な結果を達成する方法はありますか?私は自分のクラスとメソッドを書くことができると思いますが、Pythonが既にそれを行う方法を持っているなら、車輪を再発明したくありません。

50
Ryan B. Lynch

これはどう?

>>> 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

コメントには、投稿されたすべてのソリューションの速度の違いに関する良い議論があります。私は少し偏っているかもしれませんが、私が話している速度はこの問題の関数を作成してモジュールをインポートするのと比べてかなり重要ではないので、個人的にはワンライナーに固執しますが、非常に大量にこれを行う予定がある場合私が提供したものよりも速いので、提供された他の回答を見てみたいと思うかもしれません。

64

これらのリストの理解はしばらくすると面倒になります。

私はこのPythonicアプローチが好きです:

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

コードをすべて超高性能にする必要がある場合:

# 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
26
Triptych

可能性の1つは、operatorモジュールの itemgetter 関数を使用することです。

import operator

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

itemgetterの呼び出しは、渡されたものに対してfoo[0]と同等の処理を行う関数を返します。 mapを使用して、その関数を各Tupleに適用し、情報を新しいリストに抽出してから、通常どおり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]
10
Jarret Hardie

リスト内包表記とindex()でこれを行うことができます

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
5
Alasdair

Triptychへのコメントとしてこれを配置しますが、評価が不足しているため、まだコメントできません。

列挙子メソッドを使用して、タプルのリスト内のサブインデックスを照合します。例えば.

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
2
Nisan.H

この質問 に触発されて、私はこれが非常にエレガントだと感じました:

>>> 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
2
Claudiu

わかりました、vals(j)の間違いかもしれません、修正は:

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
dulce ambrocio
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)
1

私は次のことが最善の方法ではないと思います(スピードとエレガンスの懸念)が、まあ、それは役立つかもしれません:

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メソッドを使用できます。

0
jerome

Pythonのlist.index(x)は、リスト内で最初にxが出現するインデックスを返します。そのため、リスト圧縮によって返されたオブジェクトを渡して、インデックスを取得できます。

>>> 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]

同じ行で、一致する要素が複数ある場合にインデックスのリストを取得することもできます。

>>> 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]
0
dspmeng
z = list(Zip(*Tuple_list))
z[1][z[0].index('persimon')]
0
eyaler

ラムダを示唆するボディはありませんか?

Yこれを試して動作します。私は答えを探してこの投稿に来ました。好きだとは思わないが、気分が良い:P

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

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

編集して例を追加:

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

条件によってすべてのアイテムを抽出します:filter(lambda x:x [0] == "pato"、l)#[['pato'、2、1]、['pato'、2、2]、['pato'、 2、2]]

インデックス付きの条件によってすべてのアイテムを抽出します。

    >>> 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]]

注:_変数は対話型インタープリターでのみ機能しますy通常のテキストファイル_明示的な割り当てが必要です、つまり_ = filter(lambda x:x [1] [0] == "pato"、enumerate(l))

0
Wallebot