Numeri di ordinamento Python TTK TreeView
Domanda
Sto cercando di utilizzare la funzione di ordinamento TTK.TreeView illustrata nella risposta a questa domanda ( TKTreeView Column Sort ) E funziona bene per stringhe come 'ABC', 'BCD', 'CDE', ecc., Ma quando provo a ordinare i numeri che finisce per mostrare così:
1
10
11
2
3
...
.
Vorrei che i dati vengano ordinati in modo tale che l'output sia:
1
2
3
...
10
11
.
So che i valori nelle colonne TreeView sono stringhe e che probabilmente dovrò convertirle in interi prima di ordinare, ma non riesco a capire come farlo.
Soluzione
list.sort
Metodo, sorted
Accetta il parametro key
opzionale.Il valore di ritorno della funzione viene utilizzato come tasto di confronto.
Specifica della funzione key
che converti l'elemento TreeView in numero risolverà il problema.
Esempio:
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()
.
Altri suggerimenti
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))