Jaki byłby najbardziej Pythonowy sposób na znalezienie pierwszego indeksu na liście, który jest większy niż x?
Na przykład z
list = [0.5, 0.3, 0.9, 0.8]
Funkcja
f(list, 0.7)
wróci
2.
Jaki byłby najbardziej Pythonowy sposób na znalezienie pierwszego indeksu na liście, który jest większy niż x?
Na przykład z
list = [0.5, 0.3, 0.9, 0.8]
Funkcja
f(list, 0.7)
wróci
2.
2ponieważ” 0.9 > 0.7czy „ponieważ” 0.8 > 0.7? Innymi słowy, czy wyszukujesz sekwencyjnie, czy w kolejności rosnących wartości?
Odpowiedzi:
next(x[0] for x in enumerate(L) if x[1] > 0.7)
next(), ale może to za czytelność:next(i for i,v in enumerate(L) if v > 0.7)
itertools.chain()zamiast dodawać takie listy.
next((i for i, x in enumerate(L) if x > value), -1)
jeśli lista jest posortowana, bisect.bisect_left(alist, value)jest szybsza w przypadku dużej listy niż next(i for i, x in enumerate(alist) if x >= value).
bisect_leftjest O (log n), podczas gdy listcomp jest O (n), tj. im większy n, tym większa przewaga po bisect_left()stronie. Próbowałem znaleźć indeks 500_000w range(10**6)użyciu bisect_left()-> 3,75 mikrosekund i używając genexpr z next()-> 51,0 milisekund [ 10_000razy] wolniej, jak oczekiwano.
filter(lambda x: x>.7, seq)[0]
bisect_left()(najszybsze) i enumerate().
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2
IndexError: list index out of range. Korzystanie index = next[ n for n,i in enumerate(alist) if i>0.7 ]błąd otrzymujemy: NameError: name 'index' is not defined. nextjest nieco szybszy: różnica czasu wynosi 12,7 ns w porównaniu z 11,9 ns dla 60 000 liczb.
for index, elem in enumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
Inny:
map(lambda x: x>.7, seq).index(True)
1) NUMPY ARGWHERE, ogólne listy
Jeśli z przyjemnością używasz numpy, na ogólnych listach (posortowanych lub nieposortowanych) będą działać następujące czynności:
numpy.argwhere(np.array(searchlist)>x)[0]
lub jeśli potrzebujesz odpowiedzi w postaci listy:
numpy.argwhere(np.array(searchlist)>x).tolist()[0]
lub jeśli potrzebujesz odpowiedzi w postaci liczby całkowitej:
numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]
2) NUMPY SEARCHSORTED, posortowane listy (bardzo wydajne przy wyszukiwaniu list)
Jeśli jednak twoja lista wyszukiwania jest posortowana, znacznie czystsze i przyjemniejsze jest użycie funkcji np.searchsorted :
numpy.searchsorted(searchlist,x)
Zaletą korzystania z tej funkcji jest to, że oprócz wyszukiwania pojedynczej wartości x, x może być również listą, tj. Można również zwrócić listę indeksów dla listy wyszukiwanych wartości [x1, x2, x3 .. xn ], ( i jest to bardzo wydajne w porównaniu ze zrozumieniem listy w tym przypadku ).
Miałem podobny problem, gdy moja lista była bardzo długa. rozwiązania oparte na zrozumieniu lub filtrowaniu przeszłyby przez całą listę. itertools.takewhile przerwie pętlę, gdy warunek stanie się fałszywy za pierwszym razem:
from itertools import takewhile
def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])
l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)
Wiem, że jest już wiele odpowiedzi, ale czasami mam wrażenie, że słowo pythonic jest tłumaczone na „jednolinijkowy”.
Kiedy myślę, że lepsza definicja jest bliższa tej odpowiedzi :
„Wykorzystywanie funkcji języka Python do tworzenia kodu, który jest jasny, zwięzły i łatwy w utrzymaniu”.
Chociaż niektóre z powyższych odpowiedzi są zwięzłe, nie uważam ich za jasne i zrozumienie ich zajmie trochę czasu początkującym programistom, dlatego nie są one niezwykle łatwe w utrzymaniu dla zespołu zbudowanego na wielu poziomach umiejętności.
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: break
return l.index(i)
f(l,.7)
lub
l = [0.5, 0.3, 0.9, 0.8]
def f(l, x):
for i in l:
if i >x: return l.index(i)
f(l,.7)
Myślę, że powyższe jest łatwo zrozumiałe dla początkujących i nadal jest wystarczająco zwięzłe, aby zaakceptować je każdy doświadczony programista Pythona.
Myślę, że pisanie głupiego kodu jest pozytywne.
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2
Możesz to również zrobić za pomocą numpy:
import numpy as np
list(np.array(SearchList) > x).index(True)
Spróbuj tego:
def Renumerate(l):
return [(len(l) - x, y) for x,y in enumerate(l)]
przykładowy kod:
Renumerate(range(10))
wynik:
(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)