Bir liste ["foo", "bar", "baz"]
ve listedeki bir öğe verildiğinde "bar"
, dizinini ( 1
) Python'da nasıl edinebilirim ?
Bir liste ["foo", "bar", "baz"]
ve listedeki bir öğe verildiğinde "bar"
, dizinini ( 1
) Python'da nasıl edinebilirim ?
Yanıtlar:
>>> ["foo", "bar", "baz"].index("bar")
1
Referans: Veri Yapıları> Listeler Hakkında Daha Fazla Bilgi
Not Bu belki soruyu cevaplamak için en temiz yolu ise o istedi olarak , index
bir oldukça zayıf bir bileşendir list
API ve ben öfke kullanmış son kez hatırlayamıyorum. Yorumlarda bana bu cevaba yoğun bir şekilde atıfta bulunulduğu için daha eksiksiz yapılması gerektiği belirtildi. Bazı uyarılar list.index
takip ediyor. Muhtemelen başlangıçta bunun için belgelere bir göz atmaya değer:
list.index(x[, start[, end]])
Değeri x'e eşit olan ilk öğe listesinde sıfır temelli dizin döndürür .
ValueError
Böyle bir öğe yoksa bir yükseltir .İsteğe bağlı başlangıç ve bitiş bağımsız değişkenleri dilim gösterimindeki gibi yorumlanır ve aramayı listenin belirli bir alt dizisiyle sınırlamak için kullanılır. Döndürülen dizin, başlangıç bağımsız değişkeni yerine tam dizinin başlangıcına göre hesaplanır.
bir index
çağrı, bir eşleşme bulana kadar listenin her öğesini sırayla kontrol eder. Listeniz uzunsa ve kabaca listenin neresinde gerçekleştiğini bilmiyorsanız, bu arama bir darboğaz haline gelebilir. Bu durumda, farklı bir veri yapısı düşünmelisiniz. Maçı kabaca nerede bulacağınızı biliyorsanız index
bir ipucu verebileceğinizi unutmayın . Örneğin, bu pasajda l.index(999_999, 999_990, 1_000_000)
kabaca beş büyüklük sırası düzden daha hızlıdır l.index(999_999)
, çünkü birincisi sadece 10 giriş aramak zorundadır, ikincisi ise bir milyon arar:
>>> 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
Bir index
eşleşme bulana kadar listede arama yapmak için yapılan bir çağrı ve orada durana . Daha fazla eşleşme indeksine ihtiyacınız varsa, bir liste kavrama 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
Eskiden kullandığım çoğu yer index
, şimdi daha genelleştirilebilir oldukları için bir liste kavrama veya jeneratör ifadesi kullanıyorum. Yani index
, ulaşmayı düşünüyorsanız , bu mükemmel Python özelliklerine bir göz atın.
Bir çağrı index
bir sonuçlardan ValueError
öğesi 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 bulunmuyorsa,
item in my_list
(temiz, okunabilir yaklaşım) veyaindex
Aramayı try/except
yakalayan bir bloğa sarın ValueError
(muhtemelen daha hızlı, en azından aranacak liste uzun olduğunda ve öğe genellikle mevcutsa).index()
, tamsayı listelerine göre liste kavrayışından% 90'ın biraz altında olduğunu buldum .
Python'u öğrenmede gerçekten yararlı olan bir şey, interaktif yardım işlevini 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
|
Bu genellikle sizi aradığınız yönteme yönlendirir.
Cevapların çoğu tek bir endeksin nasıl bulunacağını açıklıyor , ancak öğe listede birden çok kez bulunuyorsa 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()
Fonksiyon sadece ise, ilk geçtiği döndürürenumerate()
tüm oluşumları döndürür.
Bir liste olarak:
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']
İşte bir başka küçük çözüm itertools.count()
(numaralandırma ile 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, büyük listeler için kullanmaktan daha etkilidir 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
index()
değerin ilk dizinini döndürür !
| dizin (...)
| L.index (değer; [başlangıç; [durdur]]) -> tamsayı - değerin ilk dizinini döndü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"])
Öğ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
a = ["foo","bar","baz",'bar','any','much']
indexes = [index for index in range(len(a)) if a[index] == 'bar']
Aradığınız öğenin listede olup olmadığını kontrol etmek için bir koşul ayarlamanız gerekir
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
Burada önerilen tüm işlevler doğal dil davranışını yeniden oluşturur, ancak neler olup bittiğini gizler.
[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 neden istisna işlemeli bir işlev yazmalısınız?
Tüm dizinleri istiyorsanız, NumPy'yi kullanabilirsiniz :
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),)
Net, okunabilir bir çözümdür.
Python'da içeren bir liste verilen bir öğenin dizinini bulma
Bir liste
["foo", "bar", "baz"]
ve listedeki bir öğe"bar"
için, dizinini (1) Python'da almanın en temiz yolu nedir?
Elbette, ilk oluşumun dizinini döndüren dizin yöntemi var:
>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1
Bu yöntemle ilgili birkaç sorun var:
ValueError
Değer eksikse, simgesini yakalamanız gerekir ValueError
.
Bunu, aşağıdaki gibi yeniden kullanılabilir bir tanımla yapabilirsiniz:
def index(a_list, value):
try:
return a_list.index(value)
except ValueError:
return None
Ve şu şekilde kullanın:
>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1
Ve bunun dezavantajı, döndürülen değerin is
veya is not
Hiçbirinin:
result = index(a_list, value)
if result is not None:
do_something(result)
Daha fazla olay yaşarsanız, aşağıdakilerle ilgili tam bilgi alamazsınızlist.index
:
>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar') # nothing at index 3?
1
Dizinleri anlamak için bir liste sıralayabilirsiniz:
>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]
Herhangi bir durumunuz yoksa, sonucun boolean kontrolü ile bunu kontrol edebilir veya sadece sonuçlar üzerinde döngü yaparsanız hiçbir şey yapamazsınız:
indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
do_something(index)
Pandalarınız varsa, bu bilgileri bir Series nesnesiyle kolayca alabilirsiniz:
>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0 foo
1 bar
2 baz
3 bar
dtype: object
Karşılaştırma denetimi bir dizi boole döndürür:
>>> series == 'bar'
0 False
1 True
2 False
3 True
dtype: bool
Bu boole serilerini alt simge notasyonu ile seriye aktarın ve sadece eşleşen üyelere sahip olun:
>>> series[series == 'bar']
1 bar
3 bar
dtype: object
Yalnızca dizinleri istiyorsanız, index özelliği bir tamsayı dizisi döndürür:
>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')
Ve onları bir listede veya grupta istiyorsanız, bunları yapıcıya iletin:
>>> list(series[series == 'bar'].index)
[1, 3]
Evet, numaralandırma ile bir liste kavrayışı da kullanabilirsiniz, ancak bu kadar zarif değil, bence - C'de yazılı yerleşik kodun üstesinden gelmek yerine Python'da eşitlik testleri yapıyorsunuz:
>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]
XY problemi, gerçek probleminiz yerine denediğiniz çözümü soruyor.
Neden bir listede bir öğe verilen dizine ihtiyacınız olduğunu düşünüyorsunuz?
Değeri zaten biliyorsanız, neden bir listede olduğunu umursuyorsunuz?
Değer orada değilse, yakalamak ValueError
oldukça ayrıntılı - ve bundan kaçınmayı tercih ederim.
Genellikle liste üzerinde yineleme yapıyorum, bu yüzden genellikle numaralandırma ile dizin almak, herhangi bir ilginç bilgilere bir işaretçi tutacağım .
Verileri munging ediyorsanız, muhtemelen gösterdiğim saf Python geçici çözümlerinden çok daha zarif araçlara sahip pandalar kullanmalısınız.
İhtiyacım olduğunu hatırlamıyorum list.index
, kendim. Ancak, Python standart kütüphanesine baktım ve bunun için bazı mükemmel kullanımlar görüyorum.
idlelib
GUI ve metin ayrıştırma için bunun birçok kullanımı vardır .
keyword
Modül kullanır bunu otomatik olarak metaprogramlama aracılığı anahtar kelime listesini yenilemek için modülde açıklama işaretleri bulmak için.
Lib / mailbox.py'de sıralı bir eşleme gibi kullanıyor gibi görünüyor:
key_list[key_list.index(old)] = new
ve
del key_list[key_list.index(key)]
Lib / http / cookiejar.py'de, gelecek ay almak için kullanılıyor gibi görünüyor:
mon = MONTHS_LOWER.index(mon.lower())+1
Bir öğeye kadar bir dilim almak için distutils'e benzer Lib / tarfile.py'de:
members = members[:members.index(tarinfo)]
Lib / pickletools.py'de:
numtopop = before.index(markobject)
Bu kullanımların ortak olarak göründüğü şey, kısıtlı boyutlar listelerinde çalışıyor gibi görünmeleridir (O (n) arama süresi nedeniyle önemlidir list.index
ve çoğunlukla ayrıştırmada (ve Boşta durumunda UI) kullanıldıklarıdır.
Bunun için kullanım durumları olsa da, oldukça nadirdir. Kendinizi bu cevabı ararken bulursanız, kendinize yaptığınız şeyin kullanım durumunuz için dil tarafından sağlanan araçların en doğrudan kullanımı olup olmadığını sorun.
İşlevli tüm dizinler zip
:
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')
Enumerate (alist) ile, x öğesi aradığınız şeye eşit olduğunda listenin dizini olan ilk öğeyi (n) saklayabilirsiniz.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Bu işlev, öğeyi ve listeyi bağımsız değişken olarak alır ve öğenin daha önce gördüğümüz gibi listedeki konumunu döndürür.
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"))
Çıktı
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Çıktı:
0
4
Başka seçenek
>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
... indices.append(a.index(b,offset))
... offset = indices[-1]+1
...
>>> indices
[0, 3]
>>>
... dizini almadan önce öğenin varlığını onaylamak gibi. Bu yaklaşımla ilgili güzel olan şey, fonksiyonun her zaman bir indeks listesi döndürmesidir - boş bir liste olsa bile. Dizelerle de çalışır.
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
retval = []
last = 0
while val in l[last:]:
i = l[last:].index(val)
retval.append(last + i)
last += i + 1
return retval
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
Etkileşimli bir python penceresine yapıştırıldığında:
Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
... """Always returns a list containing the indices of val in the_list"""
... retval = []
... last = 0
... while val in the_list[last:]:
... i = the_list[last:].index(val)
... retval.append(last + i)
... last += i + 1
... return retval
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
Head-down python geliştirmenin bir yıl sonra, orijinal cevabımdan biraz utanıyorum, bu yüzden kaydı düz ayarlamak için kesinlikle yukarıdaki kodu kullanabilirsiniz; ancak, aynı davranışı elde etmenin çok daha deyimsel yolu, enumerate () işlevinin yanı sıra liste kavrayışı kullanmak olacaktır.
Bunun gibi bir şey:
def indices(l, val):
"""Always returns a list containing the indices of val in the_list"""
return [index for index, value in enumerate(l) if value == val]
l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')
Bu, etkileşimli bir python penceresine yapıştırıldığında şunları sağlar:
Python 2.7.14 |Anaconda, Inc.| (default, Dec 7 2017, 11:07:58)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
... """Always returns a list containing the indices of val in the_list"""
... return [index for index, value in enumerate(l) if value == val]
...
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>>
Ve şimdi, bu soruyu ve bütün cevapları inceledikten sonra, bu tam olarak ne olduğunu fark FMC onun önerilen önceki yanıt . Bu soruyu ilk başta cevapladığım zaman, bu cevabı bile görmedim , çünkü anlamadım. Umarım biraz daha ayrıntılı örneğimin anlamaya yardımcı olacağını umarım.
Kod tek satır yukarıda hala varsa yok size mantıklı, ben çok size Google'ın piton liste anlama 'tavsiye ve yakından tanımak için birkaç dakika sürebilir. Kod geliştirmek için Python'u kullanmanın bir zevk olmasını sağlayan birçok güçlü özellikten sadece biri.
FMc ve user7177'nin cevabındaki bir varyant, herhangi bir giriş için tüm endeksleri geri gönderebilecek bir dikte verecektir:
>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>>
Tek bir giriş için tüm indeksleri almak için bunu tek bir astar olarak da kullanabilirsiniz. Verimlilik için hiçbir garanti yok, ancak lambda'nın kaç kez çağrıldığını azaltmak için set (a) kullandım.
L listesindeki x öğesinin dizinini bulma:
idx = L.index(x) if (x in L) else -1
Python listeleri sıfır tabanlı olduğundan, zip yerleşik işlevini aşağıdaki gibi kullanabiliriz:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
burada "samanlık" söz konusu listedir ve "iğne" aranacak öğedir.
(Not: Burada, dizinleri almak için i'yi tekrarlıyoruz, ancak öğelere odaklanmak yerine j'ye geçebiliriz.)
index()
Öğe bulunamadığı takdirde Python yöntemi bir hata atar. Bunun yerine , öğenin bulunmaması durumunda indexOf()
dönen JavaScript işlevine benzer hale getirebilirsiniz -1
:
try:
index = array.index('search_keyword')
except ValueError:
index = -1
Bunun daha işlevsel bir cevabı var.
list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))
Daha genel bir form:
def get_index_of(lst, element):
return list(map(lambda x: x[0],\
(list(filter(lambda x: x[1]==element, enumerate(lst))))))
Scala
/ fonksiyonel programlama meraklıları için evde hissediyor
Sahip lst
olduğunuz listeye bir isim verelim . Listeyi lst
bir numpy array
. Ve sonra listede seçilen öğenin dizinini almak için numpy.where komutunu kullanın. Bunu nasıl uygulayacağınız aşağıda açıklanmıştır.
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
Benim gibi başka bir dilden gelenler için, belki de basit bir döngü ile anlamak ve kullanmak daha kolaydır:
mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
if item == "bar":
print(index, item)
Ben şükrediyorum Peki numaralandırma tam olarak ne yapıyor? . Bu anlamama yardımcı oldu.
Bir kez bir dizin bulacaksanız "index" yöntemini kullanmak iyidir. Ancak, verilerinizi bir kereden fazla arayacaksanız bisect modülünü kullanmanızı öneririm . İki modül modülünün kullanımının sıralanması gerektiğini unutmayın. Böylece verileri bir kez sıralarsınız ve sonra bisect'i kullanabilirsiniz. Kullanılması kenarortay benim makinede modülü hızlı indeks yöntemi kullanılarak 20 katına hakkındadır.
Python 3.8 ve üstü sözdizimini kullanan bir kod örneği:
import bisect
from timeit import timeit
def bisect_search(container, value):
return (
index
if (index := bisect.bisect_left(container, value)) < len(container)
and container[index] == value else -1
)
data = list(range(1000))
# value to search
value = 666
# times to test
ttt = 1000
t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)
print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")
Çıktı:
t1=0.0400, t2=0.0020, diffs t1/t2=19.60
Çok sayıda cevapta, yerleşik yöntemin list.index(item)
yönteminin bir O (n) algoritması olduğu belirtilmektedir. Bunu bir kez yapmanız gerekiyorsa sorun değil. Ancak, öğelerin dizinlerine birkaç kez erişmeniz gerekiyorsa, önce öğe dizini çiftlerinin bir sözlüğünü (O (n)) oluşturmak ve ardından her ihtiyacınız olduğunda dizine O (1) 'den erişmek daha mantıklıdır. o.
Listenizdeki öğelerin asla tekrarlanmadığından eminseniz, şunları yapabilirsiniz:
myList = ["foo", "bar", "baz"]
# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))
# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.
Yinelenen öğeleriniz varsa ve tüm dizinlerini döndürmeniz gerekiyorsa:
from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]
# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
myDict[e].append(i)
# Lookup
myDict["foo"] # Returns [0, 4]
@TerryA tarafından belirtildiği gibi, birçok cevap bir endeksin nasıl bulunacağını tartışır .
more_itertools
, bir yinelenebilir alan içindeki birden çok dizini bulmak için araçlar içeren üçüncü taraf bir kütüphanedir .
verilmiş
import more_itertools as mit
iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]
kod
Birden fazla gözlemin indekslerini bulun:
list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]
Birden fazla öğeyi test et:
list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]
Ayrıca ile daha fazla seçeneğe bakın more_itertools.locate
. Yoluyla yükleyin > pip install more_itertools
.
sözlük kullanarak, önce listeyi işleyin ve ardından dizini buna ekleyin
from collections import defaultdict
index_dict = defaultdict(list)
word_list = ['foo','bar','baz','bar','any', 'foo', 'much']
for word_index in range(len(word_list)) :
index_dict[word_list[word_index]].append(word_index)
word_index_to_find = 'foo'
print(index_dict[word_index_to_find])
# output : [0, 5]
bence ["foo", "bar", "baz"].index("bar")
iyi ama yeterli değil çünkü "bar" sözlükte değilse, ValueError
yükseltilmiş.Bu yüzden bu işlevi kullanabilirsiniz:
def find_index(arr, name):
try:
return arr.index(name)
except ValueError:
return -1
if __name__ == '__main__':
print(find_index(["foo", "bar", "baz"], "bar"))
ve sonuç:
1
ve ad arr değerinde değilse, işlev -1 döndürür. örneğin:
yazdır (find_index (["foo", "bar", "baz"], "fooo"))
-1
l = [1, 2]; find_index(l, 3)
dönecekti -1
ve l[find_index(l, 3)]
dönecekti 2
. -1 geri dönmek için kötü bir şey, sadece geri dönmek Yok.
"bar"
, [2] Tüm endeksleri"bar"
?