Jak uzyskać pozycję przedmiotu na liście?

169

Iteruję po liście i chcę wydrukować indeks elementu, jeśli spełnia określony warunek. Jak bym to zrobił?

Przykład:

testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
    if item == 1:
        print position
Sean
źródło

Odpowiedzi:

280

Hmmm. Była tu odpowiedź ze zrozumieniem listy, ale zniknęła.

Tutaj:

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

Przykład:

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

Aktualizacja:

OK, potrzebujesz wyrażenia generatora, będziemy mieć wyrażenie generatora. Oto ponownie rozumienie listy, w pętli for:

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

Teraz skonstruujemy generator ...

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

i dość sprytnie, możemy przypisać to do zmiennej i używać jej stamtąd ...

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

I pomyśleć, że pisałem FORTRAN.

Charlie Martin
źródło
6
Po prawdopodobnie 25 latach kwestionowania programowania funkcjonalnego, myślę, że w końcu mam wskazówkę. rozumienie listy to bomba.
Charlie Martin
15
Zakładam, że masz na myśli „pojedynczą literę” i szczerze mówiąc, dłuższe imię w tym przykładzie nie zawierałoby więcej informacji.
Charlie Martin
2
Dzięki za świetną odpowiedź. Myślę, że komentarz @ gwoździarki może odnosić się do faktu, że używasz „i” w dwóch różnych kontekstach w jednym wierszu w przykładzie generatora; jeden w zrozumieniu, a drugi do iteracji przez to. Wiem, że to mnie zrzuciło na sekundę.
Brązowy
1
@CharlieMartin Używasz „i” jako indeksu zamiast elementu, zgodnie z jedną wspólną konwencją dla zmiennych jednoznakowych. Nazwanie indeksu „indeksem” i „pozycją” wyeliminowałoby niejednoznaczność. Dodatkowo odpowiadasz rodzicowi, który użył „pozycji” i „pozycji” i dobrze jest nie zmieniać niepotrzebnie części oryginalnego kodu w swojej odpowiedzi.
mikemaccana
1
Super składnia: o) Możesz łatwo uzyskać parametr wiersza poleceń. Niech istnieje szereg argumentów: args = ['x', '-p1', 'v1', '-p2', 'v2']. Następnie polecenie args[[i for i, x in enumerate(args) if x == '-p1'][0] + 1]powraca'v1'
Theodor Keinstein
170

A co z następującymi?

print testlist.index(element)

Jeśli nie jesteś pewien, czy element, którego szukasz, faktycznie znajduje się na liście, możesz dodać wstępne sprawdzenie, na przykład

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

lub

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

lub „sposób pythonowy”, którego nie lubię tak bardzo, ponieważ kod jest mniej przejrzysty, ale czasami jest bardziej wydajny,

try:
    print testlist.index(element)
except ValueError:
    pass
mmj
źródło
5
zamiast testować przed uzyskaniem dostępu, możesz po prostu spróbować sprawdzićValueError
kratenko
Myślę, że chce znaleźć wszystkie wystąpienia, wydaje się, że podajesz tylko pierwsze.
tfv
@tfv Nie widzę, jak możesz dojść do takiego wniosku, ponieważ pytanie mówi „przedmiot”, a nie „przedmioty”.
mmj
40

Użyj wyliczenia:

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position
zdan
źródło
10
for i in xrange(len(testlist)):
  if testlist[i] == 1:
    print i

xrange zamiast zakresu zgodnie z żądaniem (patrz komentarze).

jakber
źródło
zamień range () na xrange () - range () tworzy listę, xrange () tworzy iterator. xrange () zużywa mniej pamięci, a wywołanie początkowe jest szybsze.
gnud
2
Zgadzam się na duże listy w programach Python 2. Zwróć uwagę, że „zakres” nadal będzie działał w Pythonie 3 (i będzie działał jak xrange IIRC). „Xrange” idzie drogą dinozaurów.
jakber
2
Aktualizacja: xrangejest dezaktywowany w Pythonie 3.x, ponieważ nowy rangejest staryxrange
tim-oh
5

Oto inny sposób, aby to zrobić:

try:
   id = testlist.index('1')
   print testlist[id]
except ValueError:
   print "Not Found"
Phil Rankin
źródło
3
[x for x in range(len(testlist)) if testlist[x]==1]
user1713952
źródło
2

Wypróbuj poniższe:

testlist = [1,2,3,5,3,1,2,1,6]    
position=0
for i in testlist:
   if i == 1:
      print(position)
   position=position+1
B Prashantkumar
źródło
1

Jeśli twoja lista jest wystarczająco duża i spodziewałeś się znaleźć wartość tylko w rzadkiej liczbie indeksów, weź pod uwagę, że ten kod może działać znacznie szybciej, ponieważ nie musisz iterować każdej wartości na liście.

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

Jeśli spodziewasz się, że znajdziesz dużo wartości, prawdopodobnie powinieneś po prostu dodać „index” do listy i wydrukować listę na końcu, aby zaoszczędzić czas na iterację.


źródło
Zrobiłem kilka testów czasowych. Technika rozumienia listy działa 38% szybciej niż ten kod. (Zastąpiłem twoją instrukcję print wywołaniem
outputlist.append
Zrobiłem również kilka testów z listami o wielkości 100000 losowych wartości od 1 do 100. Kod, który napisałem, był w niektórych przypadkach dwukrotnie szybszy. Żadne testowanie czasowe nie jest porównywalne z aplikacją plakatu (muszą oczywiście sprawdzić się, aby mieć pewność). Przepraszam, jeśli moja opinia była szkodliwa dla tego postu.
0

Myślę, że przydałoby się użycie metody curselection () z biblioteki Tkinter:

from Tkinter import * 
listbox.curselection()

Ta metoda działa na widżetach listbox Tkinter, więc musisz utworzyć jeden z nich zamiast listy.

Spowoduje to zwrócenie takiej pozycji:

('0',) (chociaż późniejsze wersje Tkintera mogą zamiast tego zwracać listę int)

Która dotyczy pierwszej pozycji, a liczba będzie się zmieniać w zależności od pozycji pozycji.

Więcej informacji można znaleźć na tej stronie: http://effbot.org/tkinterbook/listbox.htm

Pozdrowienia.

xXAngelJinXx
źródło
1
Ciekawy pomysł. Ponieważ wymaga to jednak zaimportowania całej biblioteki Tkinter, nie jest to najskuteczniejszy sposób rozwiązania problemu.
seaotternerd
3
To jest tak nieefektywna i kręta ścieżka, że ​​powiedziałbym, że jest to zła odpowiedź, nawet jeśli w pewnym stopniu odpowiada na pytanie.
Ta odpowiedź nie ma nic wspólnego z pytaniem.
Cody Piersall
0

Po co komplikować sprawy?

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position
Abhishek
źródło
0

Aby zilustrować kompletny przykład wraz z tym, input_listktóry ma searies1(przykład: lista_wejściowa [0]), w którym chcesz series2wyszukać (przykład: lista_wejściowa [1]) i uzyskać indeksy serii2, jeśli istnieje w serii1.

Uwaga: Twoja certain conditionwola zostanie wyrażona w wyrażeniu lambda, jeśli warunki są proste

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)

wynik:

[0, 2, 6]
ravibeli
źródło
-2
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
    if id == 1:
        print testlist[id]

Myślę, że dokładnie tego chcesz. ;-) 'id' będzie zawsze indeksem wartości na liście.

Leonardo
źródło