python ttk treeview trier des nombres
Question
Je suis en train d'utiliser le ttk.Treeview fonction de tri illustré dans la réponse à cette question (Les savoirs traditionnels treeview colonne de tri) et il fonctionne très bien pour les chaînes de caractères comme 'abc', 'bcd', 'fac', etc., mais quand j'essaie de trier les nombres, il finit par montrer comme ceci:
1
10
11
2
3
...
J'aimerais pour que les données soient triées telle que la sortie est:
1
2
3
...
10
11
Je sais que les valeurs dans le treeview colonnes sont des chaînes de caractères et que je suis plus susceptible de besoin de les convertir en nombres entiers avant de les trier, mais je ne peux pas comprendre comment le faire.
La solution
list.sort
la méthode, sorted
la fonction accepte en option key
le paramètre.La valeur de retour de la fonction est utilisé comme comparaison clé.
La spécification key
fonction de convertir le treeview article dans le numéro de résoudre votre problème.
Exemple:
try:
from tkinter import *
from tkinter import ttk
except ImportError:
from Tkinter import *
import ttk
def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(key=lambda t: int(t[0]), reverse=reverse)
# ^^^^^^^^^^^^^^^^^^^^^^^
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
tv.heading(col,
command=lambda: treeview_sort_column(tv, col, not reverse))
root = Tk()
columns = ('number',)
treeview = ttk.Treeview(root, columns=columns, show='headings')
for t in ('1', '10', '11', '2', '3'):
treeview.insert('', END, values=(t,))
treeview.pack()
for col in columns:
treeview.heading(col, text=col,
command=lambda c=col: treeview_sort_column(treeview, c, False))
mainloop()
Autres conseils
I figure I'd add this bit of code for anyone wanting to use the above solution for both regular string sorts and numeric sorts.
def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
try:
l.sort(key=lambda t: int(t[0]), reverse=reverse)
# ^^^^^^^^^^^^^^^^^^^^^^^
except ValueError:
l.sort(reverse=reverse)
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))
It took me a while to find a variant of this answer, but I thought I would post an answer for those looking to sort dates as a string (i.e. 'DD/MM/YYYY')
import datetime
def treeview_sort_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(key=lambda: x, datetime.datetime.strptime(x[0], '%d/%m/%y'), reverse=reverse)
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse))