Die Frage ist nicht eindeutig. Ist die Antwort 2weil 0.9 > 0.7oder weil 0.8 > 0.7? Mit anderen Worten, suchen Sie nacheinander oder in der Reihenfolge steigender Werte?
+1: Obwohl ich es vorziehen würde, die magischen Zahlen zu vermeiden: next (idx für idx, Wert in Aufzählung (L), wenn Wert> 0,7)
Truppo
37
+1 für die Einfachheit und next(), aber vielleicht für die Lesbarkeit:next(i for i,v in enumerate(L) if v > 0.7)
Will Hardy
13
Dies sieht zwar gut aus, aber der Fall, in dem kein Ergebnis vorliegt, führt zu einer verwirrenden StopIteration.
Virgil Dupras
2
@flybywire: next()ist in 2.6+. Nennen Sie die next()Methode des Genex in früheren Versionen.
Ignacio Vazquez-Abrams
3
@Wim: Aber dann kehren Sie zur Auswertung der gesamten Sequenz zurück. Verwenden Sie itertools.chain()diese Option, anstatt solche Listen hinzuzufügen.
Ignacio Vazquez-Abrams
35
Wenn die Liste sortiert ist, bisect.bisect_left(alist, value)ist sie für eine große Liste schneller als next(i for i, x in enumerate(alist) if x >= value).
Schöne Antwort - Es war definitiv 5 bis 6 Mal schneller für mich, eine kleine sortierte Liste mit 4 Elementen zu verwenden, aber (nicht sicher, ob ich einen Fehler mache), aber wenn ich dies mit timeit mit einer langen Liste von 10000 Element-Numpy-Arrays zeitlich festlege Ich finde es ungefähr doppelt so langsam wie die Antwort auf das Listenverständnis oben, worüber ich überrascht war.
Adrian Tompkins
1
@AdrianTompkins: Mit Ihrem Benchmark stimmt etwas nicht. bisect_leftist O (log n), während listcomp O (n) ist, dh je größer der n, desto mehr Vorteil auf der bisect_left()Seite. Ich habe versucht , finden Index 500_000in range(10**6)Verwendung bisect_left()-> 3,75 Mikrosekunden und mit Hilfe des genexpr mit next()-> 51,0 Millisekunden [ 10_000mal] langsamer als erwartet.
@truppo Filter in Python 3 gibt einen Generator zurück, also sollte es nicht schlechter sein als ein Listenverständnis? Auch finde ich diesen Weg besser lesbar als die Aufzählungslösung.
BubuIIC
Eine Sache, die an diesem nicht gut ist, ist, dass Sie in die Ausnahmebehandlung geraten, wenn kein Element in der Sequenz größer als .7 ist.
Brian C.
Die Lösung ist technisch falsch. Der Frageautor fragte, wie der Index des Elements in der Liste gefunden werden kann. Diese Lösung gibt jedoch stattdessen einen Datensatz zurück. Eventmore in Python 3.8 ist es langsamer als bisect_left()(am schnellsten) und enumerate().
Sergey Nevmerzhitsky
16
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i inenumerate(alist) if i>0.7 ][0]
2
es wird fehlschlagen, wenn 'x' größer als jeder andere Wert in der Liste ist
mshsayem
2
@mshsayem: Das Problem ist für diesen Fall schlecht definiert. Ein Misserfolg kann das Richtige sein.
S.Lott
@ S.Loot: Guter Punkt. Wenn dies nicht in der Liste enthalten ist, führt dies zu einem verständlichen Fehler, wenn dies einer Variablen zugewiesen wird : IndexError: list index out of range. Die Verwendung von index = next[ n for n,i in enumerate(alist) if i>0.7 ]Fehler ergibt : NameError: name 'index' is not defined. nextist etwas schneller: Der Zeitunterschied beträgt 12,7 ns gegenüber 11,9 ns für 60 000 Nummern.
Leo
10
for index, elem inenumerate(elements):
if elem > reference:
return index
raise ValueError("Nothing Found")
Ich hatte ein ähnliches Problem, als meine Liste sehr lang war. Verständnis oder filterbasierte Lösungen würden die ganze Liste durchlaufen. itertools.takewhile unterbricht die Schleife, sobald die Bedingung beim ersten Mal falsch wird:
from itertools import takewhile
deff(l, b):returnlen([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)
warum schreibst du nicht def f (l, b): return len (list (takewhile (lambda x: x [1] <= b, enumerate (l))))?
Avo Asatryan
2
Ich weiß, dass es bereits viele Antworten gibt, aber manchmal habe ich das Gefühl, dass das Wort Python in "Einzeiler" übersetzt wird.
Wenn ich denke, dass eine bessere Definition dieser Antwort näher kommt :
"Nutzen Sie die Funktionen der Python-Sprache, um Code zu erstellen, der klar, präzise und wartbar ist."
Obwohl einige der oben genannten Antworten prägnant sind, finde ich sie nicht klar und es würde eine Weile dauern, bis ein Programmieranfänger sie versteht, sodass sie für ein Team mit vielen Fähigkeiten nicht besonders wartbar sind.
l = [0.5, 0.3, 0.9, 0.8]
deff(l, x):for i in l:
if i >x: breakreturn l.index(i)
f(l,.7)
oder
l = [0.5, 0.3, 0.9, 0.8]
deff(l, x):for i in l:
if i >x: return l.index(i)
f(l,.7)
Ich denke, dass das Obige für einen Neuling leicht verständlich ist und immer noch prägnant genug ist, um von jedem erfahrenen Python-Programmierer akzeptiert zu werden.
Ich denke, das Schreiben von dummem Code ist positiv.
Das sieht ziemlich schick aus. Aber theoretisch wird es die gesamte Liste durchlaufen und dann das erste Ergebnis (größer als x) zurückgeben, oder? Gibt es eine Möglichkeit, eine zu erstellen, die direkt nach dem ersten Ergebnis stoppt?
c00kiemonster
Was ist falsch daran, die ganze Liste zu durchlaufen? Wenn der erste Wert größer als 0,7 am Ende der Liste liegt, macht dies keinen Unterschied.
Ghostdog74
3
Wahr. Aber in diesem speziellen Fall sind die Listen, für die ich die Funktion verwenden möchte, ziemlich lang, daher würde ich es vorziehen, das Durchlaufen zu beenden, sobald eine Übereinstimmung gefunden wird ...
c00kiemonster
ob es lang ist oder nicht, wenn der erste Wert das letzte zweite Element der Liste ist, müssen Sie immer noch die gesamte Liste durchlaufen, um dorthin zu gelangen!
Ghostdog74
4
@ ghostdog74: Ja, aber dies ist kein Grund zu wollen, dass alle Fälle die schlimmsten Fälle sind.
Onkel Bens
0
Sie können dies auch tun mit numpy:
import numpy as np
list(np.array(SearchList) > x).index(True)
2
weil0.9 > 0.7
oder weil0.8 > 0.7
? Mit anderen Worten, suchen Sie nacheinander oder in der Reihenfolge steigender Werte?Antworten:
next(x[0] for x in enumerate(L) if x[1] > 0.7)
quelle
next()
, aber vielleicht für die Lesbarkeit:next(i for i,v in enumerate(L) if v > 0.7)
next()
ist in 2.6+. Nennen Sie dienext()
Methode des Genex in früheren Versionen.itertools.chain()
diese Option, anstatt solche Listen hinzuzufügen.Wenn die Liste sortiert ist,
bisect.bisect_left(alist, value)
ist sie für eine große Liste schneller alsnext(i for i, x in enumerate(alist) if x >= value)
.quelle
bisect_left
ist O (log n), während listcomp O (n) ist, dh je größer dern
, desto mehr Vorteil auf derbisect_left()
Seite. Ich habe versucht , finden Index500_000
inrange(10**6)
Verwendungbisect_left()
-> 3,75 Mikrosekunden und mit Hilfe des genexpr mitnext()
-> 51,0 Millisekunden [10_000
mal] langsamer als erwartet.filter(lambda x: x>.7, seq)[0]
quelle
bisect_left()
(am schnellsten) undenumerate()
.>>> alist= [0.5, 0.3, 0.9, 0.8] >>> [ n for n,i in enumerate(alist) if i>0.7 ][0] 2
quelle
IndexError: list index out of range
. Die Verwendung vonindex = next[ n for n,i in enumerate(alist) if i>0.7 ]
Fehler ergibt :NameError: name 'index' is not defined
.next
ist etwas schneller: Der Zeitunterschied beträgt 12,7 ns gegenüber 11,9 ns für 60 000 Nummern.for index, elem in enumerate(elements): if elem > reference: return index raise ValueError("Nothing Found")
quelle
Noch einer:
map(lambda x: x>.7, seq).index(True)
quelle
Ich hatte ein ähnliches Problem, als meine Liste sehr lang war. Verständnis oder filterbasierte Lösungen würden die ganze Liste durchlaufen. itertools.takewhile unterbricht die Schleife, sobald die Bedingung beim ersten Mal falsch wird:
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)
quelle
Ich weiß, dass es bereits viele Antworten gibt, aber manchmal habe ich das Gefühl, dass das Wort Python in "Einzeiler" übersetzt wird.
Wenn ich denke, dass eine bessere Definition dieser Antwort näher kommt :
"Nutzen Sie die Funktionen der Python-Sprache, um Code zu erstellen, der klar, präzise und wartbar ist."
Obwohl einige der oben genannten Antworten prägnant sind, finde ich sie nicht klar und es würde eine Weile dauern, bis ein Programmieranfänger sie versteht, sodass sie für ein Team mit vielen Fähigkeiten nicht besonders wartbar sind.
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)
oder
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)
Ich denke, dass das Obige für einen Neuling leicht verständlich ist und immer noch prägnant genug ist, um von jedem erfahrenen Python-Programmierer akzeptiert zu werden.
Ich denke, das Schreiben von dummem Code ist positiv.
quelle
1) NUMPY SOLUTION, allgemeine Listen
Wenn Sie gerne numpy verwenden, funktioniert Folgendes für allgemeine Listen (sortiert oder unsortiert):
numpy.argwhere(np.array(searchlist)>x)[0]
oder wenn Sie die Antwort als Liste benötigen:
numpy.argwhere(np.array(searchlist)>x).tolist()[0]
oder wenn Sie die Antwort als ganzzahligen Index benötigen:
numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]
2) NUMPY SOLUTION, sortierte Listen
Wenn Ihre Suchliste jedoch sortiert ist, ist es viel sauberer und schöner, die Funktion np.searchsorted zu verwenden :
Das Schöne an dieser Funktion ist, dass Sie neben der Suche nach einem einzelnen Wert x auch eine Liste von Indizes für eine Liste von Werten x zurückgeben können ( und dies ist in diesem Fall im Vergleich zum Listenverständnis sehr effizient ).
quelle
>>> 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
quelle
Sie können dies auch tun mit
numpy
:import numpy as np list(np.array(SearchList) > x).index(True)
quelle
Probier diese:
def Renumerate(l): return [(len(l) - x, y) for x,y in enumerate(l)]
Beispielcode:
Renumerate(range(10))
Ausgabe:
(10, 0) (9, 1) (8, 2) (7, 3) (6, 4) (5, 5) (4, 6) (3, 7) (2, 8) (1, 9)
quelle