web-dev-qa-db-fra.com

Comment operator.itemgetter et sort () fonctionnent-ils en Python?

J'ai le code suivant:

# initialize
a = []

# create the table (name, age, job)
a.append(["Nick", 30, "Doctor"])
a.append(["John",  8, "Student"])
a.append(["Paul", 22, "Car Dealer"])
a.append(["Mark", 66, "Retired"])    

# sort the table by age
import operator
a.sort(key=operator.itemgetter(1))    

# print the table
print(a)

Il crée une table 4x3 puis le trie par âge. Ma question est la suivante: que fait exactement key=operator.itemgetter(1)? La fonction operator.itemgetter renvoie-t-elle la valeur de l'élément? Pourquoi ne puis-je pas taper quelque chose comme key=a[x][1] ici? Ou puis-je? Comment un opérateur peut-il imprimer une certaine valeur du formulaire, telle que 3x2, qui est 22?

  1. Comment Python trie-t-il la table? Puis-je trier à l'envers?

  2. Comment puis-je le trier en fonction de deux colonnes, comme premier âge, et si age est le même nom b?

  3. Comment pourrais-je le faire sans operator?

39
Nickl

On dirait que vous êtes un peu confus à propos de tout ça.

operator est un module intégré fournissant un ensemble d'opérateurs pratiques. En deux mots, operator.itemgetter(n) construit un objet appelable qui suppose un objet itérable (par exemple, une liste, un tuple, un ensemble) en tant qu'entrée et extrait le n-ième élément de celui-ci.

Donc, vous ne pouvez pas utiliser key=a[x][1] ici, car python n'a aucune idée de ce que x est. Au lieu de cela, vous pourriez utiliser une fonction lambda (elem est juste un nom de variable, pas de magie):

a.sort(key=lambda elem: elem[1])

Ou juste une fonction ordinaire:

def get_second_elem(iterable):
    return iterable[1]

a.sort(key=get_second_elem)

Donc, voici une remarque importante: en python, les fonctions sont des citoyens de première classe , afin que vous puissiez les transmettre à d’autres fonctions en tant que paramètre.

D'autres questions:

  1. Oui, vous pouvez inverser le tri, ajoutez simplement reverse=True: a.sort(key=..., reverse=True)
  2. Pour trier sur plusieurs colonnes, vous pouvez utiliser itemgetter avec plusieurs index: operator.itemgetter(1,2) ou avec lambda: lambda elem: (elem[1], elem[2]). De cette façon, les itérables sont construits à la volée pour chaque élément de la liste, qui sont comparés les uns contre les autres dans l'ordre lexicographique (?) (Premiers éléments comparés, si égaux - seconds éléments comparés, etc.)
  3. Vous pouvez récupérer la valeur en [3,2] à l'aide de a[2,1] (les index sont basés sur zéro). Utiliser l'opérateur ... C'est possible, mais pas aussi propre que l'indexation. 

Reportez-vous à la documentation pour plus de détails:

  1. operator.itemgetter expliqué
  2. Liste de tri par clé personnalisée en Python
77
J0HN

Réponse pour les débutants en Python

En mots plus simples: 

  1. Le paramètre key= de sort nécessite une clé fonction (à appliquer comme objets à trier) plutôt qu'une clé unique valeur et 
  2. c'est exactement ce que operator.itemgetter(1) vous donnera: Un function qui récupère le premier élément d'un objet de type liste. 

(Plus précisément ce sont callables, pas des fonctions, mais c'est une différence qui peut souvent être ignorée.)

19
Lutz Prechelt

Vous posez beaucoup de questions auxquelles vous pourriez répondre vous-même en lisant la documentation , je vais donc vous donner un conseil général: lisez-le et expérimentez dans le shell Python. Vous verrez que itemgetter renvoie un appelable:

>>> func = operator.itemgetter(1)
>>> func(a)
['Paul', 22, 'Car Dealer']
>>> func(a[0])
8

Pour le faire différemment, vous pouvez utiliser lambda:

a.sort(key=lambda x: x[1])

Et l'inverser:

a.sort(key=operator.itemgetter(1), reverse=True)

Trier par plus d'une colonne:

a.sort(key=operator.itemgetter(1,2))

Voir le triing How To .

10
Paulo Almeida
a = []
a.append(["Nick", 30, "Doctor"])
a.append(["John",  8, "Student"])
a.append(["Paul",  8,"Car Dealer"])
a.append(["Mark", 66, "Retired"])
print a

[['Nick', 30, 'Doctor'], ['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Mark', 66, 'Retired']]

def _cmp(a,b):     

    if a[1]<b[1]:
        return -1
    Elif a[1]>b[1]:
        return 1
    else:
        return 0

sorted(a,cmp=_cmp)

[['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]

def _key(list_ele):

    return list_ele[1]

sorted(a,key=_key)

[['John', 8, 'Student'], ['Paul', 8, 'Car Dealer'], ['Nick', 30, 'Doctor'], ['Mark', 66, 'Retired']]
>>> 
0
shubham sinha