Soru Python'da bir liste içeren bir öğenin dizinini bulma


Bir liste için ["foo", "bar", "baz"] ve listedeki bir öğe "bar", Python'daki dizinini (1) nasıl alabilirim?


2247
2017-10-07 01:39


Menşei


Geri dönüyor musunuz: [1] Birden fazla örnek olması durumunda en düşük endeks "bar", [2] Tüm endeksleri "bar"? - Mulliganaceous
a) Maddenin listede olduğu garanti ediliyor mu, yoksa hata meselesini nasıl ele almalıyız? (return None / raise ValueError) b) Liste girişlerinin benzersiz olması garanti edilir ve bir maçın ilk indeksini mi yoksa tüm endeksleri mi döndürmeliyiz? - smci


Cevaplar:


>>> ["foo", "bar", "baz"].index("bar")
1

Referans: Veri Yapıları> Listeler Hakkında Daha Fazla Bilgi

Uyarılar takip

Bu soruya cevap vermenin belki de en temiz yolu olmasına dikkat edin. istendiği gibi, index oldukça zayıf bir bileşenidir list API ve son kez öfkeyle kullandığımı hatırlayamıyorum. Bu cevaba ağır bir şekilde atıfta bulunulduğu için daha eksiksiz yapılması gerektiği yorumlarında bana işaret edilmiştir. Hakkında bazı uyarılar list.index takip et. Muhtemelen başlangıçta doktora bir göz atmaya değer:

>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.

Liste uzunluğunda doğrusal zaman karmaşıklığı

bir index çağrı, bir eşleşme bulana kadar listenin tüm öğelerini sırayla kontrol eder. Listeniz uzunsa ve liste içinde kabaca nerede olduğunu bilmiyorsanız, bu arama bir darboğaz olabilir. Bu durumda farklı bir veri yapısı düşünmelisiniz. Eşleşmeyi nerede bulacağınızı biliyorsanız, index Bir ipucu. Örneğin, bu snippet’te l.index(999_999, 999_990, 1_000_000) yaklaşık beş katı büyüklükten daha hızlıdır l.index(999_999)Çünkü, eskiden sadece 10 giriş aramak zorunda, ikincisi ise bir milyonu arıyor:

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

Sadece indeksini döndürür ilk maç argümanına

Bir çağrı index bir eşleşme bulana kadar sırayla arama yapar ve orada durur. Daha fazla eşleşme endeksine ihtiyacınız varsa, liste anlama veya jeneratör ifadesi kullanmalısınız.

>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2

Bir zamanlar kullanacağım çoğu yer indexŞimdi daha genelleştirilebilir olduklarından bir liste anlama veya jeneratör ifadesi kullanıyorum. Yani eğer ulaşmayı düşünüyorsanız indexBu mükemmel python özelliklerine bir göz atın.

Öğe listede bulunmuyorsa atar

Bir çağrı index sonuç olarak ValueError öğe mevcut değilse.

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

Öğe listede bulunmayabilirse, ya

  1. Önce ile kontrol et item in my_list (temiz, okunabilir yaklaşım) veya
  2. Sarın index içinde ara try/except yakalayan blok ValueError (muhtemelen, arama yapılacak liste uzun olduğunda ve öğe genellikle mevcut olduğunda daha hızlıdır).

3308
2017-10-07 01:40



Listede olmaması ve hata yapıp yapmadığını bilmek! - JokerMartini
index değeri "bar" olan ilk öğeyi döndürür. Listede iki kez "bar" varsa, ikinci "bar" için anahtarı bulamazsınız. Belgelere bakın: docs.python.org/3/tutorial/datastructures.html - mpoletto
Nasıl numpy dizi için bunu yapmak için? - Hendy Irawan
Maddenin listede yer aldığı hususunda şart koşulmuştur. - Alex Coventry
@smci, bunu işaretlediğiniz için teşekkürler. - Alex Coventry


Python öğrenmede gerçekten yararlı olan bir şey interaktif yardım fonksiyonunu kullanmaktır:

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

genellikle sizi aradığınız yönteme yönlendirir.


786
2017-10-07 13:19





Cevapların çoğunluğu nasıl bulunacağını açıklıyor tek bir endeksAncak, öğe listede birden çok kez varsa, yöntemleri birden çok dizin döndürmez. kullanım enumerate():

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

index() işlev sadece ilk oluşumu döndürürken, enumerate() tüm oluşumları döndürür.

Liste kavraması olarak:

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

İşte başka bir küçük çözüm itertools.count() (bu, numaralandırmayla hemen hemen aynı yaklaşımdır):

from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

Bu, daha büyük listelerde kullanmaktan daha verimlidir enumerate():

$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop

446
2018-06-19 22:31



Numaralandırma benim için indeks tabanlı yöntemlerden daha iyi çalışır, çünkü 'beginwith' kullanarak dizelerin indekslerini toplamaya çalışıyorum ve birden fazla oluşumları topladım ya da indeksi "beginwith" ile kullanmanın bir yolu var. anlayamadım - Tupelo Thistlehead
Ellerimde, numaralandırılmış sürüm sürekli olarak biraz daha hızlıdır. Yukarıdaki ölçümler yayınlandığından bazı uygulama ayrıntıları değişmiş olabilir. - Alex Coventry
@AlexCoventry Yüksek derecede bilgisayar özelliklerine bağlıdır, ancak neredeyse beş yıldır (vay zaman sinekleri), size katılıyorum. Özellikle beri izip python 3 ile gereksiz yapıldı - TerryA


Tüm endeksleri almak için:

 indexes = [i for i,x in enumerate(xs) if x == 'foo']

123
2018-06-25 15:07





index()döndürür ilk değer endeksi!

| indeksi (...)
   | L.index (değer, [başlangıç, [dur]]) -> tamsayı - değer ilk değerini döndürür

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

105
2017-08-30 09:40



Ve listede bulunmuyorsa? - Peter Mortensen
Ne döndüğünü görmek için kodu çalıştırmayı denediniz mi? :-) - HongboZhu


Öğe listede değilse bir sorun ortaya çıkar. Bu işlev sorunu ele alır:

# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None

67
2018-04-16 10:19





a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']

57
2017-08-21 12:01



'item' çok yanıltıcı değişken bir isimdir. 'index' belki? - johan d.


Aradığınız öğenin listede olup olmadığını kontrol etmek için bir koşul belirlemeniz gerekir.

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None

39
2018-05-26 04:26





Buradaki önerilen işlevlerin tümü, içsel dil davranışını yeniden üretiyor, ancak neler olduğunu anlıyor.

[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly

Dil, istediğiniz şeyi yapmak için yöntemler sağlıyorsa, istisna elleçleme işleviyle neden bir işlev yazılır?


34
2018-05-16 16:45



3. yöntem listenin iki kez yinelenir, değil mi? - Eric Duminil
Yeniden: "Burada önerilen işlevlerin hepsi": Yazma zamanında belki, ama hala doğru olup olmadığını görmek için daha yeni cevapları kontrol etmelisin. - Peter Mortensen


Tüm dizinleri istiyorsanız, o zaman kullanabilirsiniz NumPy:

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

Açık, okunabilir bir çözümdür.


27
2017-11-17 19:05



Dizelerin listeleri, sayısal olmayan nesnelerin listesi vb. Nedir? - Laryx Decidua


Python'da bir liste içeren bir öğenin dizinini bulma

Bir liste için ["foo", "bar", "baz"] ve listedeki bir öğe "bar", Python'da indeksini (1) almanın en temiz yolu nedir?

Tabii, ilk olayın indeksini döndüren indeks yöntemi var:

>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1

Bu yöntemle ilgili birkaç sorun var:

  • Değer listede yoksa, bir ValueError
  • Eğer değerden daha fazlası listede ise, sadece ilk olanın indeksini alırsınız.

Değer yok

Eğer değer eksikse, ValueError.

Bu şekilde yeniden kullanılabilir bir tanımla yapabilirsiniz:

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

Ve bunun gibi kullanın:

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

Ve bunun dezavantajı, geri dönüş değeri olup olmadığını muhtemelen kontrol etmenizdir. is veya is not Yok:

result = index(a_list, value)
if result is not None:
    do_something(result)

Listede birden fazla değer

Daha fazla olayınız varsa, değil ile tam bilgi almak list.index:

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

Dizinleri bir listeyi anlama listesine girebilirsiniz:

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

Herhangi bir oluşumunuz yoksa, sonucun boole kontrolü ile kontrol edebilir ya da sonuçların üstesinden gelmeniz durumunda hiçbir şey yapamazsınız:

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

Pandalarla daha iyi veri paylaşımı

Eğer pandalarınız varsa, bu bilgiyi bir dizi nesnesi ile kolayca edinebilirsiniz:

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

Bir karşılaştırma kontrolü bir dizi boole dönüşü olacaktır:

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

Bu dizi boole dizisini altyazı gösterimi ile seriye aktarın ve sadece eşleşen üyeleri edinin:

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

Yalnızca dizinleri istiyorsanız, index özelliği bir dizi tam sayı döndürür:

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

Bunları bir liste halinde veya tuple da istiyorsanız, bunları sadece kurucuya iletin:

>>> list(series[series == 'bar'].index)
[1, 3]

Evet, sayımla bir liste kavrayışını da kullanabilirsiniz, ama bu sadece o kadar zarif değil, benim düşüncemde - Python'da eşitlik testleri yapıyorsunuz.

>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]

Bu bir XY sorunu?

XY problemi, gerçek probleminizden ziyade sizin denediğiniz çözümü sormaktır.

Listede bir öğe verilen dizine neden ihtiyaç duyuyorsunuz?

Değeri zaten biliyorsanız, neden listede olduğuyla ilgileniyorsunuz?

Değer orada değilse, ValueError oldukça verbose - ve bundan kaçınmayı tercih ederim.

Genelde yine de liste üzerinde yinelemeyi yapıyorum, bu yüzden genellikle herhangi bir ilginç bilgi için bir işaretçi tutacağım numaralandır.

Verileri topluyorsanız, muhtemelen pandaları kullanmalıydınız - ki gösterdiğim saf Python çözümlerinden çok daha şık araçlara sahip.

İhtiyacı hatırlamıyorum list.index, kendim. Ancak, Python standart kütüphanesini inceledim ve bunun için bazı mükemmel kullanımlar gördüm.

Bunun için birçok, birçok kullanım var idlelibGUI ve metin ayrıştırma için.

keyword modül, metaprogramlama yoluyla içindeki anahtar kelime listesini otomatik olarak yeniden oluşturmak için modülde yorum işaretçileri bulmak için kullanır.

Lib / mailbox.py dosyasında, düzenli bir haritalama gibi görünüyor.

key_list[key_list.index(old)] = new

ve

del key_list[key_list.index(key)]

Lib / http / cookiejar.py dosyasında, bir sonraki aya geçmek için kullanılmış gibi görünüyor:

mon = MONTHS_LOWER.index(mon.lower())+1

Lib / tarfile.py dosyasında, bir öğeye kadar bir dilim almak için dağınıklıklara benzer:

members = members[:members.index(tarinfo)]

Lib / pickletools.py dosyasında:

numtopop = before.index(markobject)

Bu kullanımların ortak olarak göründüğü şey, kısıtlı boyutlarda listelerinde çalıştıklarıdır (O (n) arama süresi için önemlidir list.index) ve çoğunlukla ayrıştırmada kullanılırlar (ve Idle durumunda UI).

Bunun için kullanım durumları olsa da, oldukça nadirdir. Kendinizi bu cevabı ararken bulursanız, kullanım durumunuz için dil tarafından sağlanan araçların en doğrudan kullanımı olup olmadığını kendinize sorun.


22
2017-08-22 03:08