J'apprends le python en autodidacte et parfois il me manquerait un professeur pour des choses qui doivent être basiques, là je bute sur un truc qui doit pas être foufou:
Comment comparer l'élément d'une liste au suivant sans avoir un index out of range?
Je comprends bien d'où vient le problème avec le dernier élément de la liste qui n'a pas de suivant, mais je ne sais pas comment feinter.
Par exemple avec ce code:
for i, e in enumerate(items): if e == items[i+1]: items.pop(i)
Au lieu de pop, je passe par une seconde liste sur laquelle je *.append(x) les éléments à conserver du coup.
Je ne sais pas si c'est optimal mais bon... ça semble fonctionner.
Si y a mieux je suis preneur, ce genre de détails manquent quand on apprend seul. Parfois j'écris 20 lignes et je vois que ça pourrait n'en prendre qu'une.
Comment comparer l'élément d'une liste au suivant sans avoir un index out of range?
for i, e in enumerate(items): if e == items[i+1]: items.pop(i)
Le problème est que tu utilises enumerate sur lequel tu n'as aucun contrôle. Lorsque tu veux parcourir une liste (ou une séquence) avec des conditions portant sur des valeurs de la liste en fonction des indices (du genre l'indice suivant, l'indice précédent, le deuxième indice, l'avant-dernier indice, etc), il est bien plus simple d'utiliser un range approprié. Typiquement, pour savoir si une liste est croissante, tu peux écrire :
def estCroissante(L):
for i in range(len(L)-1):
if L[i+1]<L[i]:
return False
return True
L=[42, 47, 53]
print(estCroissante(L))
C'est considéré comme peu pythonnique et c'est plus lent qu'un code qui évite d'accéder à l'élément de la liste avec le crochet. Mais si tu débutes, c'est la solution à envisager.
Peut-être mais algorithmiquement inefficace puisque chacun des slices effectue un parcours des listes (et même une copie des références) ce qui entraîne trois parcours au total. Et le temps n'est pas extraordinaire, je pensais que ça aurait mieux, c'est très comparable au temps du code que j'ai donné (qui est lent à cause des appels à __getitem__). Ci-dessous d'autres approches :
def estCroissante0(L):
for i in range(len(L)-1):
if L[i+1]<L[i]:
return False
return True
def estCroissante1(L):
it=iter(L)
next(it)
for (a, b) in zip(L, it):
if a>b:
return False
return True
def estCroissante2(L):
it=iter(L)
next(it)
for i, z in enumerate(it):
if L[i]>z:
return False
return True
def estCroissante3(L):
return all([a<=b for a,b in zip(L[:-1], L[1:])])
L=list(range(5*10**6))
from time import perf_counter
begin_perf = perf_counter()
print(estCroissante0(L))
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
begin_perf = perf_counter()
print(estCroissante1(L))
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
begin_perf = perf_counter()
print(estCroissante2(L))
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
begin_perf = perf_counter()
print(estCroissante3(L))
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
True
Temps d'exécution : 0.36s
True
Temps d'exécution : 0.16s
True
Temps d'exécution : 0.27s
True
Temps d'exécution : 0.34s
EDIT Oui, utiliser sorted est plus rapide si la liste est croissante mais peut être beaucoup plus lent si la liste n'est pas croissante, imaginer une liste de 10 millions d'entiers commençant par 1, 0.
J'imagine que cela est dû à la façon dont all() est implanté dans python.
from time import perf_counter
def f():
for i in [j for j in range(10**7)]:
pass
def g():
for i in (j for j in range(10**7)):
pass
begin_perf = perf_counter()
f()
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
begin_perf = perf_counter()
g()
delta = perf_counter() - begin_perf
print(f"Temps d'exécution : {delta:.2f}s")
Temps d'exécution : 0.63s
Temps d'exécution : 0.48s
édit : non ce n'est pas all() qui est en cause , je viens de le vérifier.
Ni zip() à priori...
- Edité par __fabien 16 mars 2021 à 22:57:43
J'aime les bananes, le python, le gnu, le pingouin.
J'aime les bananes, le python, le gnu, le pingouin.
Vive le libre !
Comparaison de liste
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Découverte Python Doc Tkinter Les chaînes de caractères
Le Tout est souvent plus grand que la somme de ses parties.
Découverte Python Doc Tkinter Les chaînes de caractères
Découverte Python Doc Tkinter Les chaînes de caractères
Découverte Python Doc Tkinter Les chaînes de caractères
Le Tout est souvent plus grand que la somme de ses parties.
Découverte Python Doc Tkinter Les chaînes de caractères