Pergunta

Eu estou tentando usar a ttk.Treeview função de ordenação ilustrado na resposta a esta pergunta (Tk treeview coluna de classificação) e ele funciona muito bem para seqüências de caracteres como 'abc', 'bcd', 'cde", etc., mas quando eu tento ordenar os números que ele acaba aparecendo como este:

1
10
11
2
3
...

Eu gostaria que os dados sejam ordenados de tal forma que a saída é:

1
2
3
...
10
11

Eu sei que os valores em treeview colunas são cadeias de caracteres e que eu sou provavelmente vai precisar convertê-las para números inteiros antes de ordenar, mas eu não consigo descobrir como fazer isso.

Foi útil?

Solução

list.sort método, sorted a função de aceitar opcional key o parâmetro.O valor de retorno da função é utilizado como chave de comparação.

Especificando key função que converte o item de treeview em número vai resolver o seu problema.

Exemplo:

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()

enter image description here

Outras dicas

Eu acho que eu tinha adicionar um pouco de código para quem quiser usar a solução acima para regular o tipo de seqüência de caracteres e o numérico tipos.

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))        

Levei um tempo para encontrar uma variante desta resposta, mas eu pensei que eu ia postar uma resposta para aqueles que procuram classificar as datas como uma seqüência de caracteres (por exemplo,'DD/MM/AAAA')

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))  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top