Bagaimana menemukan semua kemunculan elemen dalam daftar?


378

index()hanya akan memberikan kemunculan pertama item dalam daftar. Apakah ada trik rapi yang mengembalikan semua indeks dalam daftar?


1
Saya agak bingung dengan pertanyaan ini: apakah Anda ingin mencari item secara rekursif di semua tingkat daftar multidimensi, atau apakah Anda hanya ingin mencari kejadian di tingkat atas daftar?
Anderson Green

22
Menurut pendapat saya harus ada metode daftar yang melakukan ini.
otocan

Jawaban:


545

Anda dapat menggunakan pemahaman daftar:

indices = [i for i, x in enumerate(my_list) if x == "whatever"]

3
Pada ular sanca yang lebih tua, gunakan filter () untuk fungsionalitas yang pada dasarnya sama.
Gleno

44
Pemahaman daftar muncul dalam python di 2.0, enumeratedi 2.3. Jadi ya, jika Python Anda kuno, gunakan filter().
Steven Rumbalski

2
Teknik ini tidak akan menemukan semua kemunculan item dalam array multidimensi. Misalnya, print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])mengembalikan []bukan [[0, 1], [0, 0], [1, 1]].
Anderson Green

10
@AndersonGreen: Istilah "array multidimensi" menunjukkan struktur data yang dijamin memiliki ukuran seragam di sepanjang masing-masing kapaknya. Tidak ada struktur data seperti itu di Python biasa. Ada daftar daftar, tetapi mereka sangat berbeda dari "array multidimensi". Jika Anda menginginkan yang terakhir, Anda harus mempertimbangkan menggunakan NumPy, yang memungkinkan Anda melakukan hal-hal seperti (a == 1).nonzero()untuk array NumPy a.
Sven Marnach

2
@MadmanLee Jika Anda menginginkan sesuatu yang cepat, gunakan NumPy. Lihat jawaban JoshAdel
Georgy

117

Meskipun bukan solusi untuk daftar secara langsung, numpysangat bersinar untuk hal semacam ini:

import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]

pengembalian:

ii ==>array([2, 8])

Ini bisa secara signifikan lebih cepat untuk daftar (array) dengan sejumlah besar elemen vs beberapa solusi lainnya.


2
Saya perhatikan [0] pada akhirnya mengubah apa yang akan menjadi array ke string. Saya ingin tahu mengapa Anda memilih untuk melakukan ini.
amelia

5
@amelia [0]diperlukan karena akan wheremengembalikan tuple(array([2, 8], dtype=int64),)
Winand

1
Hey @ Win dan saya memasukkan [0] tetapi masih mendapatkan kedua bagian. Ini kode saya: (nrg.local_logs.all_id_resp_address adalah daftar) "ste =" 199.38.164.165 "value = np.where (nrg.local_logs.all_id_resp_address == ste) [0]" Saya akan senang jika Anda dapat memberi tahu saya apa yang saya lakukan salah
Tomer

2
@ Pelanggan pertama-tama all_id_resp_addressseharusnya np.arraytidak list.
Menangkan dan

1
@Tomer Anda mencoba untuk membandingkan listdan str, jelas Anda lulus Falseke np.where. Ketika Anda membandingkan np.arraydengan sesuatu Anda mendapatkan array nilai boolean. Kemudian np.wheretemukan posisi semua Truenilai array itu.
Menangkan dan

29

Solusi menggunakan list.index:

def indices(lst, element):
    result = []
    offset = -1
    while True:
        try:
            offset = lst.index(element, offset+1)
        except ValueError:
            return result
        result.append(offset)

Ini jauh lebih cepat daripada pemahaman daftar enumerate, untuk daftar besar. Ini juga jauh lebih lambat daripada numpysolusi jika Anda sudah memiliki array, jika tidak biaya konversi melebihi kenaikan kecepatan (diuji pada daftar bilangan bulat dengan elemen 100, 1000 dan 10000).

CATATAN: Catatan kehati-hatian berdasarkan komentar Chris_Rands: solusi ini lebih cepat dari pemahaman daftar jika hasilnya cukup jarang, tetapi jika daftar memiliki banyak contoh elemen yang sedang dicari (lebih dari ~ 15% dari daftar) , pada tes dengan daftar 1000 bilangan bulat), pemahaman daftar lebih cepat.


3
Anda mengatakan ini lebih cepat dari daftar comp, dapatkah Anda menunjukkan timing Anda yang menunjukkan ini?
Chris_Rands

5
Ini sudah lama sekali, saya mungkin menggunakan timeit.timeitdaftar yang dibuat secara acak. Tapi itu poin penting, dan saya kira itu sebabnya Anda bertanya. Pada saat itu tidak terpikir oleh saya, tetapi peningkatan kecepatan hanya benar jika hasilnya cukup jarang. Saya baru saja menguji dengan daftar penuh elemen untuk mencari, dan itu jauh lebih lambat daripada pemahaman daftar.
Paulo Almeida

18

Bagaimana tentang:

In [1]: l=[1,2,3,4,3,2,5,6,7]

In [2]: [i for i,val in enumerate(l) if val==3]
Out[2]: [2, 4]

10
occurrences = lambda s, lst: (i for i,e in enumerate(lst) if e == s)
list(occurrences(1, [1,2,3,1])) # = [0, 3]

8

more_itertools.locate menemukan indeks untuk semua item yang memenuhi syarat.

from more_itertools import locate


list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]

list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]

more_itertoolsadalah perpustakaan pihak ketiga > pip install more_itertools.


1
bisa menyenangkan jika lib ini ditambahkan ke conda-forge (meskipun conda installtelah berubah sangat tidak stabil dalam kinerja akhir-akhir ini)
matanster

4

Satu lagi solusi (maaf jika duplikat) untuk semua kejadian:

values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)

4

Atau Gunakan range(python 3):

l=[i for i in range(len(lst)) if lst[i]=='something...']

Untuk (python 2):

l=[i for i in xrange(len(lst)) if lst[i]=='something...']

Dan kemudian (kedua kasus):

print(l)

Seperti yang diharapkan.


4

Menggunakan filter () di python2.

>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]

2

Anda dapat membuat defaultdict

from collections import defaultdict
d1 = defaultdict(int)      # defaults to 0 values for keys
unq = set(lst1)              # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
      d1[each] = lst1.count(each)
else:
      print(d1)

2

Mendapatkan semua kemunculan dan posisi satu atau lebih item (identik) dalam daftar

Dengan enumerate (daftar) Anda dapat menyimpan elemen pertama (n) yang merupakan indeks daftar ketika elemen x sama dengan apa yang Anda cari.

>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

Mari kita buat fungsi kita temukan indeks

Fungsi ini mengambil item dan daftar sebagai argumen dan mengembalikan posisi item dalam daftar, seperti yang kita lihat sebelumnya.

def indexlist(item2find, list_or_string):
  "Returns all indexes of an item in a list or a string"
  return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))

Keluaran


[1, 3, 5, 7]

Sederhana

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

Keluaran:

0
4

Jawaban ini adalah yang paling mudah bagi saya untuk menerapkan kode saya yang ada.
Ryan Harris

2

Menggunakan for-loop:

  • Jawaban dengan enumeratedan pemahaman daftar lebih efisien dan pythonic, namun, jawaban ini ditujukan untuk siswa yang mungkin tidak diizinkan untuk menggunakan beberapa fungsi bawaan tersebut .
  • buat daftar kosong, indices
  • buat loop dengan for i in range(len(x)):, yang pada dasarnya beralih melalui daftar lokasi indeks[0, 1, 2, 3, ..., len(x)-1]
  • dalam loop, tambahkan i, di mana x[i]cocok dengan value, keindices
def get_indices(x: list, value: int) -> list:
    indices = list()
    for i in range(len(x)):
        if x[i] == value:
            indices.append(i)
    return indices

n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))

>>> [4, 8, 9]
  • Fungsi,, get_indicesdiimplementasikan dengan petunjuk jenis . Dalam hal ini, daftar,, nadalah sekelompok ints, oleh karena itu kami mencari value, juga didefinisikan sebagai int.

Menggunakan a while-loopdan .index:

  • Dengan .index, gunakan try-exceptuntuk penanganan kesalahan karena ValueErrorakan terjadi jika valuetidak ada dalam daftar.
def get_indices(x: list, value: int) -> list:
    indices = list()
    i = 0
    while True:
        try:
            # find an occurrence of value and update i to that index
            i = x.index(value, i)
            # add i to the list
            indices.append(i)
            # advance i by 1
            i += 1
        except ValueError as e:
            break
    return indices

print(get_indices(n, -60))
>>> [4, 8, 9]

Self-define Anda get_indeicessedikit lebih cepat (~ 15%) daripada pemahaman daftar normal. Saya mencoba mencari tahu.
Travis

1

Jika Anda menggunakan Python 2, Anda dapat mencapai fungsi yang sama dengan ini:

f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))

Di mana my_listdaftar Anda ingin mendapatkan indeks, dan valueadalah nilai yang dicari. Pemakaian:

f(some_list, some_element)

1

Jika Anda perlu mencari posisi semua elemen di antara indeks tertentu , Anda dapat menyatakannya:

[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.