2017-10-20 4 views
2

Je regardais beaucoup et lisais beaucoup de questions, mais je n'arrive pas à comprendre comment donner deux arguments à la clé de la méthode de tri, donc je peux faire une comparaison plus complexe .python, trier la liste avec deux arguments dans la fonction de comparaison

Exemple:

class FruitBox(): 
    def __init__(self, weigth, fruit_val): 
    self.weigth = weigth 
    self.fruit_val = fruit_val 

Je veux comparer le Fruitbox par fruit_val, mais! De plus, ils sont plus lourds que les autres.

Il serait donc:

f1 = FruitBox(2,5) 
f2 = FruitBox(1,5) 
f3 = FruitBox(2,4) 
f4 = FruitBox(3,4) 

boxes = [f1,f2,f3,f4] 
boxes.sort(key = ???) # here is the question 

Résultat attendu: =>[FruitBox(2,4),FruitBox(3,4),FruitBox(1,5),FruitBox(2,5)]

Est-il possible d'envoyer une fonction avec 2 arguments, quand je fais quelque chose comme

def sorted_by(a,b): 
    #logic here, I don't know what will be yet 

et moi

boxes.sort(key=sorted_by) 

Il lance:

Traceback (most recent call last): 
    File "python", line 15, in <module> 
TypeError: sort_by_b() missing 1 required positional argument: 'b' 

Comment puis-je donner deux arguments à la clé de tri?

+0

Quelles sont les deux clés que vous souhaitez trier avec? –

+0

Ce n'est pas clair. Quels sont les deux arguments? –

+0

@DanielRoseman Je voulais une fonction de comparaison (a, b), voir la réponse acceptée –

Répondre

1

Cette réponse est dédiée à répondre:

Comment puis-je donner Deux arguments à la clé de tri?


Le style ancien comparer façon de trier est allé en Python 3, comme en Python 2 que vous feriez:

def sorted_by(a,b): 
    # logic here 
    pass 

boxes.sort(cmp=sorted_by) 

Mais si vous devez l'utiliser Python 3, il est toujours là, mais dans un module, functool, son but est de convertir le cmp-key:

import functools 
cmp = functools.cmp_to_key(sorted_by) 
boxes.sort(key=cmp) 

le préféré façon de trier est de faire une fonction clé qui renvoie un poids pour le tri sur lequel baser. Voir Francisco’s réponse.

0

Vous pouvez trier en utilisant le paramètre key avec la variable membre fruit_val:

boxes = [f1,f2,f3,f4] 
boxes.sort(key=lambda x:x.fruit_val) 
print([i.__dict__ for i in boxes]) 

Sortie:

[{'fruit_val': 4, 'weigth': 2}, {'fruit_val': 4, 'weigth': 3}, {'fruit_val': 5, 'weigth': 2}, {'fruit_val': 5, 'weigth': 1}] 
+0

mmm ce n'est pas ce que je voulais –

1

Si vous voulez trier en utilisant deux touches, vous pouvez le faire comme ça (je suppose que vous voulez trier d'abord par fruit_val puis par weight:

boxes.sort(key=lambda x: (x.fruit_val, x.weigth)) 
2

Les docs, section Odd and Ends dit:

Les routines de tri sont garantis à utiliser __lt__() pour faire des comparaisons entre deux objets. Ainsi, il est facile d'ajouter un ordre de tri standard à une classe en définissant un __lt__() méthode.

Dans votre exemple, qui se traduit par l'ajout de la __lt__() à votre FruitBox classe:

class FruitBox(): 
    def __init__(self, weigth, fruit_val): 
     self.weigth = weigth 
     self.fruit_val = fruit_val 

    def __lt__(self, other): 
     # your arbitrarily complex comparison here: 
     if self.fruit_val == other.fruit_val: 
      return self.weight < other.weight 
     else: 
      return self.fruit_val < other.fruit_val 

     # or, as simple as: 
     return (self.fruit_val, self.weight) < (other.fruit_val, other.weight) 

Ensuite, utilisez simplement comme ceci:

sorted(fruitbox_objects)