【问题标题】:python ttk treeview sort numberspython ttk treeview 排序数字
【发布时间】:2014-03-28 17:39:43
【问题描述】:

我正在尝试使用该问题的答案 (Tk treeview column sort) 中说明的 ttk.Treeview 排序函数,它适用于“abc”、“bcd”、“cde”等字符串,但是当我尝试对数字进行排序时,它最终会显示如下:

1
10
11
2
3
...

我希望对数据进行排序,以使输出为:

1
2
3
...
10
11

我知道树视图列中的值是字符串,我很可能需要在排序之前将它们转换为整数,但我不知道该怎么做。

【问题讨论】:

    标签: python sorting tkinter treeview ttk


    【解决方案1】:

    list.sort 方法,sorted 函数接受可选的key 参数。函数的返回值作为比较键。

    指定 key 函数将树视图项转换为数字将解决您的问题。

    例子:

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

    【讨论】:

    • 我知道这很简单。谢谢!
    • 请注意,要使此功能与多列一起使用,您必须将排序命令定义为 command=lambda c=col: treeview_sort_column(treeview, c, False) 否则将使用非唯一的列标识符。
    • @henneray,您的评论中的c 是什么?
    • c 只是一个虚拟关键字参数,可确保 lambda 函数使用 col 的瞬时值。如果您尝试使用 2 列的代码,您将看到问题所在。它将尝试使用仅来自 col 变量的最后一次 for 循环迭代的值对每一列进行排序。因此,['numbers1','numbers2'] 两列都将按“numbers2”中的值排序。
    • @henneray,我在treeview_sort_column看到你的代码修改;据我所知,那里的代码没有你提到的问题。
    【解决方案2】:

    我想我会为任何想要将上述解决方案用于常规字符串排序和数字排序的人添加这段代码。

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

    【讨论】:

    • 感谢您花时间添加此修改。
    【解决方案3】:

    如果有人在 2020 年签到并且还需要包含浮动,那么使用这个

    l.sort(key=lambda t: float(t[0]), reverse=reverse)
    

    【讨论】:

      【解决方案4】:

      我花了一段时间才找到这个答案的变体,但我想我会为那些希望将日期排序为字符串(即“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))  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-03
        • 1970-01-01
        • 2020-08-05
        • 1970-01-01
        • 2011-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多