Listedeki öğenin konumu nasıl alınır?


169

Bir liste üzerinden yineleme yapıyorum ve belirli bir koşulu karşılarsa öğenin dizinini yazdırmak istiyorum. Bunu nasıl yaparım?

Misal:

testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
    if item == 1:
        print position

Yanıtlar:


280

Hmmm. Burada liste kavrayışı olan bir cevap vardı, ama kayboldu.

Buraya:

 [i for i,x in enumerate(testlist) if x == 1]

Misal:

>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]

Güncelleme:

Tamam, bir jeneratör ifadesi istiyorsunuz, bir jeneratör ifademiz olacak. İşte liste kavrayışı, bir for döngüsü içinde:

>>> for i in [i for i,x in enumerate(testlist) if x == 1]:
...     print i
... 
0
5
7

Şimdi bir jeneratör inşa edeceğiz ...

>>> (i for i,x in enumerate(testlist) if x == 1)
<generator object at 0x6b508>
>>> for i in (i for i,x in enumerate(testlist) if x == 1):
...     print i
... 
0
5
7

ve niftly, bunu bir değişkene atayabilir ve oradan kullanabiliriz ...

>>> gen = (i for i,x in enumerate(testlist) if x == 1)
>>> for i in gen: print i
... 
0
5
7

Ve eskiden FORTRAN yazdığımı düşünüyordum.


6
Muhtemelen 25 yıllık fonksiyonel programlamayı sorguladıktan sonra, sonunda nihayet ipucunu alıyorum. Liste anlama da bomba.
Charlie Martin

15
Sanırım "tek harf" demek istediniz ve açıkçası, bu örnekteki daha uzun bir adın daha fazla bilgi içeriği olmayacaktır.
Charlie Martin

2
Harika cevap için teşekkürler. @ Nailer'ın yorumu, jeneratör örneğindeki tek bir satırda iki farklı bağlamda 'i' kullandığınıza bağlı olabilir; biri kavrayışın içinde, diğeri de onu yinelemek için. Beni bir saniyeliğine fırlattığını biliyorum.
Kahverengi

1
@CharlieMartin Tek karakter değişkenleri için ortak bir kural uyarınca öğe yerine dizin için 'i' kullanıyorsunuz. 'İndex' dizinini ve 'item' öğesini adlandırmak belirsizliği kaldıracaktır. Ayrıca, 'item' ve 'position' kullanılan bir ebeveyne yanıt veriyorsunuz ve cevabınızdaki orijinal kodun bölümlerini gereksiz yere yeniden adlandırmamak iyi bir davranış.
mikemaccana

1
Süper sözdizimi: o) Kolayca bir komut satırı parametresi alabilirsiniz. Argümanları dizisi var edelim: args = ['x', '-p1', 'v1', '-p2', 'v2']. Sonra komut args[[i for i, x in enumerate(args) if x == '-p1'][0] + 1]geri döner'v1'
Theodor Keinstein

170

Aşağıdakiler ne olacak?

print testlist.index(element)

Aranacak öğenin listede olup olmadığından emin değilseniz, aşağıdaki gibi bir ön kontrol ekleyebilirsiniz.

if element in testlist:
    print testlist.index(element)

veya

print(testlist.index(element) if element in testlist else None)

veya kodun daha az net olduğu, ancak bazen daha verimli olduğu için çok sevmediğim "pitonik yol"

try:
    print testlist.index(element)
except ValueError:
    pass

5
erişmeden önce test etmek yerine, sadece deneyebilir ve kontrol edebilirsinizValueError
kratenko

Bence tüm olayları bulmak istiyor, sadece birincisini veriyor gibisin.
tfv

@tfv Sorunun "öğeler" değil "madde" yazdığı için bu sonuca nasıl varabileceğinizi göremiyorum.
mmj

40

Numaralandır:

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position

10
for i in xrange(len(testlist)):
  if testlist[i] == 1:
    print i

istendiği gibi aralık yerine xrange (yorumlara bakın).


range () öğesini xrange () ile değiştir - range () bir liste oluşturur, xrange () bir yineleyici oluşturur. xrange () daha az bellek kullanır ve başlangıç ​​çağrısı daha hızlıdır.
gnud

2
Python 2 programlarındaki büyük listeleri kabul ediyorum. 'Aralık' ın yine de python 3'te çalışacağını (ve xrange IIRC gibi çalışacağını) unutmayın. 'xrange' dinozorların yoluna gidiyor.
jakber

2
Güncelleme: xrangePython 3.x'te, rangeeski eskidirxrange
tim-oh

5

İşte bunu yapmanın başka bir yolu:

try:
   id = testlist.index('1')
   print testlist[id]
except ValueError:
   print "Not Found"


2

Aşağıdakileri deneyin:

testlist = [1,2,3,5,3,1,2,1,6]    
position=0
for i in testlist:
   if i == 1:
      print(position)
   position=position+1

1

Listeniz yeterince genişlediyse ve değeri yalnızca az sayıda endekste bulmayı beklediyseniz, listedeki her değeri tekrarlamak zorunda olmadığınız için bu kodun çok daha hızlı çalışabileceğini düşünün .

lookingFor = 1
i = 0
index = 0
try:
  while i < len(testlist):
    index = testlist.index(lookingFor,i)
    i = index + 1
    print index
except ValueError: #testlist.index() cannot find lookingFor
  pass

Değeri çok bulmayı bekliyorsanız, muhtemelen bir listeye "index" eklemeniz ve yineleme başına zaman kazanmak için en sonunda listeyi yazdırmanız gerekir.


Bazı zamanlama testleri yaptım. Liste anlama tekniği bu koddan% 38 daha hızlı çalışır. (Baskı
ifadenizi

Ayrıca 1 ile 100 arasında 100000 rasgele değerin liste boyutları ile bazı testler yaptım. Yazdığım kod bazı durumlarda iki kat daha hızlıydı. Hiçbir zaman testi posterin uygulamasıyla karşılaştırılamaz (elbette emin olmak için kendilerini test etmelidirler). Fikrimin bu gönderiye zararlı olup olmadığını özür dilerim.

0

Tkinter kütüphanesinden curselection () yöntemini kullanmanın yararlı olabileceğini düşünüyorum:

from Tkinter import * 
listbox.curselection()

Bu yöntem Tkinter liste kutusu widget'larında çalışır, bu nedenle bir liste yerine bunlardan birini oluşturmanız gerekir.

Bu, aşağıdaki gibi bir konum döndürür:

('0',) (Tkinter'in sonraki sürümleri bunun yerine bir ints listesi döndürebilir)

Hangi ilk pozisyon için ve sayı madde konumuna göre değişecektir.

Daha fazla bilgi için bu sayfaya bakın: http://effbot.org/tkinterbook/listbox.htm

Selamlar.


1
İlginç fikir. Bu, tüm Tkinter kütüphanesinin içe aktarılmasını gerektirdiğinden, sorunu çözmenin en etkili yolu değildir.
seaotternerd

3
Bu öyle verimsiz ve dolambaçlı bir yol ki, soruyu biraz ele alsa bile yanlış bir cevap olduğunu söyleyebilirim.

Bu cevabın soru ile ilgisi yoktur.
Cody Piersall

0

Neden işleri zorlaştırıyorsunuz?

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position

0

Sadece birlikte eksiksiz bir örnek göstermek için input_listvardır searies1(örneğin: input_list [0]) Eğer bir arama yapmak istediğiniz series2(örneğin: input_list [1]) ve SERIES1 bulunuyorsa SERIES2 indeksleri olsun.

Not: certain conditionKoşullar basitse lambda ifadesine girersiniz

input_list = [[1,2,3,4,5,6,7],[1,3,7]]
series1 = input_list[0]
series2 = input_list[1]
idx_list = list(map(lambda item: series1.index(item) if item in series1 else None, series2))
print(idx_list)

çıktı:

[0, 2, 6]

-2
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
    if id == 1:
        print testlist[id]

Sanırım tam da istediğin şey bu. ;-) 'id' her zaman listedeki değerlerin dizini olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.