【问题标题】:Natural sorting of a list in Python3Python3中列表的自然排序
【发布时间】:2019-11-14 16:32:31
【问题描述】:

我正在尝试对列表进行排序:

[
    '[fc] EDW Ratio (10 degrees)', 
    ' [fc] EDW Ratio (45 degrees)', 
    ' [fc] EDW Ratio (60 degrees)', 
    ' [fc] EDW Ratio (25 degrees)', 
    ' [fc] EDW Ratio (20 degrees)', 
    ' [fc] EDW Ratio (30 degrees)', 
    ' [fc] EDW Ratio (15 degrees)', 
    ' [fc] EDW output factor (60 degrees)', 
    ' [fc] Quality index'
]

使用已接受答案的第一部分here

但是列表最终是这样的:

[
    ' [fc] EDW Ratio (15 degrees)', 
    ' [fc] EDW Ratio (20 degrees)', 
    ' [fc] EDW Ratio (25 degrees)', 
    ' [fc] EDW Ratio (30 degrees)', 
    ' [fc] EDW Ratio (45 degrees)', 
    ' [fc] EDW Ratio (60 degrees)', 
    ' [fc] EDW output factor (60 degrees)', 
    ' [fc] Quality index', 
    '[fc] EDW Ratio (10 degrees)'
]

而我希望 EDW 比率(10 度) 在排序后位于列表的开头(索引位置 0)。

如何做到这一点?

我的代码包括以下内容:

#
# Method to define natural sorting used to sort lists
#
def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

    .
    .
    .


    tname_list = test_names.split(",") # this outputs the exact first (unsorted) list shown above

    tname_list.sort(key=natural_keys) # use human sorting defined above. This outputs the second list shown above.

【问题讨论】:

  • 嗨@2one,你能告诉我们你的代码吗?
  • natural_keys 为您的每个输入字符串返回什么?

标签: python python-3.x list natural-sort


【解决方案1】:

您的代码是正确的,但您的数据看起来不正确:所有条目都有一个前导空格,这意味着它们“在”您识别最少的那个之前,实际上没有前导空格。

如果数据正常,我建议您修改代码以忽略前导空格(检查:How do I remove leading whitespace in Python?)。

【讨论】:

  • 其他一些使代码更健壮的好答案,但这是目前的问题。我添加了如下所示的代码行,并达到了预期的效果。谢谢。
  • tname_list = [x.lstrip() for x in tname_list] # remove white space from start of list entries before sort
【解决方案2】:

您需要修改natural_keys 以仅将字符串的数字部分作为int 返回。您应该使用int() 进行转换,而不是使用atoi() 来返回字符的ascii 代码。

【讨论】:

    【解决方案3】:

    如果您的任何字符串包含多个数字,或者将数字放在字符串的开头或结尾,您将会遇到麻烦。这是因为 Python 无法将 intstr 相互比较。您的键函数应以元组或列表的形式返回。

    def atoi(text):
        return (int(text), '') if text.isdigit() else (math.nan, text)
    

    math.nan 很特别,因为它永远不会比实际数字少。

    【讨论】:

    • 感谢您也可以将其包含在内。
    【解决方案4】:

    我推荐使用natsort(完全公开,我是作者)。您的数据也有点乱,您需要删除前导空格以规范所有条目。

    from natsort import natsorted
    data = [
        '[fc] EDW Ratio (10 degrees)', 
        ' [fc] EDW Ratio (45 degrees)', 
        ' [fc] EDW Ratio (60 degrees)', 
        ' [fc] EDW Ratio (25 degrees)', 
        ' [fc] EDW Ratio (20 degrees)', 
        ' [fc] EDW Ratio (30 degrees)', 
        ' [fc] EDW Ratio (15 degrees)', 
        ' [fc] EDW output factor (60 degrees)', 
        ' [fc] Quality index'
    ]
    data_sorted = natsorted(data, key=lambda x: x.lstrip())
    

    输出

    [
     '[fc] EDW Ratio (10 degrees)',
     ' [fc] EDW Ratio (15 degrees)',
     ' [fc] EDW Ratio (20 degrees)',
     ' [fc] EDW Ratio (25 degrees)',
     ' [fc] EDW Ratio (30 degrees)',
     ' [fc] EDW Ratio (45 degrees)',
     ' [fc] EDW Ratio (60 degrees)',
     ' [fc] EDW output factor (60 degrees)',
     ' [fc] Quality index',
    ]
    

    【讨论】:

    • 谢谢,我以后再看看。
    【解决方案5】:
    import re
    
    def get_numbers(texto):
        return int(re.findall(r'[0-9]+', texto)[0])
            
    def sort_list(l):
        dicto = {}
        for i in l:
            dicto[get_numbers(i)] = i
        lista = []
        for i in sorted(list(dicto.keys())):
            lista.append(dicto[i])
        return lista
    
    sort_list(frames)
    

    请注意,它仅适用于第一组数字...“peter123jjj111”将仅考虑 123

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多