Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Classer une liste d'objets

13 réponses
Avatar
Laurent Claessens
Bonjour



J'ai une liste d'instances d'une classe que j'ai cr=E9=E9. Typiquement,

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x =3D x
self.y =3D y

P =3D Point(1,3)
Q =3D Point(2,7)
liste =3D []
liste.append(P)
liste.append(Q)

---------------------------------------------------------

Je voudrais maintenant classer la liste par ordre de l'attribut x des
objets. Je vois comment je ferais =E7a de fa=E7on tr=E8s pi=E9tonne et tr=
=E8s
peu optimis=E9e, mais est-ce qu'il y a moyen de faire vite, et propre ?

Je ne vous cache pas que dans le cas concret que j'ai en t=EAte, c'est
plus imbriqu=E9; plut=F4t genre

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x =3D x
self.y =3D y

class ligne(object):
def __init__(self,P,Q):
self.depart =3D P
self.arrive =3D Q

---------------------------------------------------------

Ensuite, j'ai une liste de lignes que je voudrais classer par
ordonn=E9es du point de d=E9part, c=E0d si L est une ligne, je voudrais
classer en fonction de

L.depart.x

Je suppose que si j'ai une solution au premier probl=E8me, je pourrai en
d=E9duire une au second probl=E8me, ainsi que des cas plus compliqu=E9s.

Merci de votre aide
Bon WE
Laurent

10 réponses

1 2
Avatar
Kobayashi
Laurent Claessens a écrit :
Bonjour



J'ai une liste d'instances d'une classe que j'ai créé. Typiquement,

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

P = Point(1,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)

---------------------------------------------------------

Je voudrais maintenant classer la liste par ordre de l'attribut x des
objets. Je vois comment je ferais ça de façon très piétonne et très
peu optimisée, mais est-ce qu'il y a moyen de faire vite, et propre ?



class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y
def __cmp__(self,other):
if self.x < other.x: return -1
if self.x > other.x: return +1
return 0


P = Point(5,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)
print [p.x for p in liste]
liste.sort()
print [p.x for p in liste]


Je ne vous cache pas que dans le cas concret que j'ai en tête, c'est
plus imbriqué; plutôt genre

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

class ligne(object):
def __init__(self,P,Q):
self.depart = P
self.arrive = Q

---------------------------------------------------------

Ensuite, j'ai une liste de lignes que je voudrais classer par
ordonnées du point de départ, càd si L est une ligne, je voudrais
classer en fonction de

L.depart.x

Je suppose que si j'ai une solution au premier problème, je pourrai en
déduire une au second problème, ainsi que des cas plus compliqués.

Merci de votre aide
Bon WE
Laurent





Avatar
Laurent Claessens
> class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y
def __cmp__(self,other):
if self.x < other.x: return -1
if self.x > other.x: return +1
return 0




Exactement ce que je cherchais ... et en prime, je crois même
comprendre la logique :)

Merci.
Laurent
Avatar
Kobayashi
Kobayashi a écrit :
Laurent Claessens a écrit :
Bonjour



J'ai une liste d'instances d'une classe que j'ai créé. Typiquement,

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

P = Point(1,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)

---------------------------------------------------------

Je voudrais maintenant classer la liste par ordre de l'attribut x des
objets. Je vois comment je ferais ça de façon très piétonne et très
peu optimisée, mais est-ce qu'il y a moyen de faire vite, et propre ?



class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y
def __cmp__(self,other):
if self.x < other.x: return -1
if self.x > other.x: return +1
return 0



Comme dirait B.D. le 06/12/2007

def __cmp__(self,other):
return cmp(self.x, other.x)




P = Point(5,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)
print [p.x for p in liste]
liste.sort()
print [p.x for p in liste]


Je ne vous cache pas que dans le cas concret que j'ai en tête, c'est
plus imbriqué; plutôt genre

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

class ligne(object):
def __init__(self,P,Q):
self.depart = P
self.arrive = Q

---------------------------------------------------------

Ensuite, j'ai une liste de lignes que je voudrais classer par
ordonnées du point de départ, càd si L est une ligne, je voudrais
classer en fonction de

L.depart.x

Je suppose que si j'ai une solution au premier problème, je pourrai en
déduire une au second problème, ainsi que des cas plus compliqués.

Merci de votre aide
Bon WE
Laurent







Avatar
Eric Brunel
On Fri, 27 Jun 2008 23:32:07 +0200, Laurent Claessens
wrote:

Bonjour



J'ai une liste d'instances d'une classe que j'ai créé. Typiquement,

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

P = Point(1,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)

---------------------------------------------------------

Je voudrais maintenant classer la liste par ordre de l'attribut x des
objets. Je vois comment je ferais ça de façon très piétonne et très
peu optimisée, mais est-ce qu'il y a moyen de faire vite, et propre ?



Et c'est un travail pour... decorate-sort-undecorate!

Les solutions à base de __cmp__ déjà données fonctionnent, mais ne sont
quelquefois pas applicables: imagine qu'à un endroit de ton appli, tu aies
besoin de trier par coordonnées x, et à un autre endroit par coordonnées
y... Vu que tu ne peux pas avoir deux méthodes __cmp__, tu es battu.

Donc, pour le cas général, la façon de faire consiste à:
- "décorer" la liste: tu construit une liste de tuples contenant d'abord
la valeur sur laquelle tu veux trier, puis l'objet d'origine.
- trier la liste "décorée"; Python triant les tuples en fonction de leurs
éléments (de gauche à droite), tu obtiens une liste triée comme tu veux,
avec les valeurs pour le tri en trop.
- virer les "décorations" de la liste pour retrouver des objets d'origine,
dans l'ordre que tu veux.

Sur ton exemple:

liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]

Et voilà!

Je ne vous cache pas que dans le cas concret que j'ai en tête, c'est
plus imbriqué; plutôt genre

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

class ligne(object):
def __init__(self,P,Q):
self.depart = P
self.arrive = Q

---------------------------------------------------------

Ensuite, j'ai une liste de lignes que je voudrais classer par
ordonnées du point de départ, càd si L est une ligne, je voudrais
classer en fonction de

L.depart.x

Je suppose que si j'ai une solution au premier problème, je pourrai en
déduire une au second problème, ainsi que des cas plus compliqués.



Tu supposes bien! Je te laisse faire; ça ne devrait pas te poser beaucoup
de problème...

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Avatar
NicolasP
> Sur ton exemple:

liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]



Tu peux expliquer la dernière ligne ?
Avatar
Bruno Desthuilliers
Eric Brunel a écrit :
On Fri, 27 Jun 2008 23:32:07 +0200, Laurent Claessens
wrote:

Bonjour



J'ai une liste d'instances d'une classe que j'ai créé. Typiquement,

-----------------------------------------

class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y

P = Point(1,3)
Q = Point(2,7)
liste = []
liste.append(P)
liste.append(Q)

---------------------------------------------------------

Je voudrais maintenant classer la liste par ordre de l'attribut x des
objets. Je vois comment je ferais ça de façon très piétonne et très
peu optimisée, mais est-ce qu'il y a moyen de faire vite, et propre ?



Et c'est un travail pour... decorate-sort-undecorate!

Les solutions à base de __cmp__ déjà données fonctionnent, mais ne sont
quelquefois pas applicables: imagine qu'à un endroit de ton appli, tu
aies besoin de trier par coordonnées x, et à un autre endroit par
coordonnées y... Vu que tu ne peux pas avoir deux méthodes __cmp__, tu
es battu.



Mais non...

Donc, pour le cas général, la façon de faire consiste à:


(snip explication du DSU)

liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]




Ou beaucoup plus simplement:

import operator
liste.sort(key=operator.attrgetter('x'))
Avatar
Eric Brunel
On Mon, 30 Jun 2008 13:28:29 +0200, NicolasP wrote:

Sur ton exemple:
liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]



Tu peux expliquer la dernière ligne ?



Sans savoir ce que tu n'as pas compris, je ne suis pas sûr de savoir quoi
expliquer... Si c'est le _ qui te trouble, on peut réécrire ça comme:
liste = [y for x, y in liste_a_trier]
Le _ est une convention quelquefois utilisée pour une variable dont le
contenu ne nous intéresse pas.

Si c'est le 'for x, y in liste' que tu ne comprends pas, voilà le
comportement sur un petit exemple:
l = [(1, 2), (2, 3), (3, 5), (4, 8), (5, 12)]
for x, y in l:






... print 'x = ', x, 'y =', y
...
x = 1 y = 2
x = 2 y = 3
x = 3 y = 5
x = 4 y = 8
x = 5 y = 12

Si c'est autre chose, il va falloir m'expliquer ce que je dois expliquer...

HTH quand même...
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"
Avatar
NicolasP
Eric Brunel a écrit :
On Mon, 30 Jun 2008 13:28:29 +0200, NicolasP wrote:

Sur ton exemple:
liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]



Tu peux expliquer la dernière ligne ?



Sans savoir ce que tu n'as pas compris, je ne suis pas sûr de savoir


Effectivement, désolé pour cette imprécision.

quoi expliquer... Si c'est le _ qui te trouble, on peut réécrire ça comme:


C'est bien le _ qui me pose problème.
liste = [y for x, y in liste_a_trier]
Le _ est une convention quelquefois utilisée pour une variable dont le
contenu ne nous intéresse pas.


Je pensais qu'il y avait un coté magique avec le _. Mais je vois que non, juste une convention de nom. Nommer une variable _ ne me viendrait pas à l'esprit. D'autant plus que dans certains langages c'est interdit.


HTH quand même...


Mais oui.

Merci

Nicolas
Avatar
Kobayashi
NicolasP a écrit :
Eric Brunel a écrit :
On Mon, 30 Jun 2008 13:28:29 +0200, NicolasP wrote:

Sur ton exemple:
liste_a_trier = [(p.x, p) for p in liste]
liste_a_trier.sort()
liste = [p for _, p in liste_a_trier]



Tu peux expliquer la dernière ligne ?



Sans savoir ce que tu n'as pas compris, je ne suis pas sûr de savoir


Effectivement, désolé pour cette imprécision.

quoi expliquer... Si c'est le _ qui te trouble, on peut réécrire ça
comme:


C'est bien le _ qui me pose problème.
liste = [y for x, y in liste_a_trier]
Le _ est une convention quelquefois utilisée pour une variable dont le
contenu ne nous intéresse pas.


Je pensais qu'il y avait un coté magique avec le _. Mais je vois que
non, juste une convention de nom. Nommer une variable _ ne me viendrait
pas à l'esprit. D'autant plus que dans certains langages c'est interdit.



Pour info., il y a une discussion sur le "_"
dans le fil plus récent "__builtin__._ ?" ...



HTH quand même...


Mais oui.

Merci

Nicolas


Avatar
NicolasP
>
Pour info., il y a une discussion sur le "_"
dans le fil plus récent "__builtin__._ ?" ...



Oui, je la lis également.
1 2