【问题标题】:How to sort alpha numeric set in python如何在python中对字母数字集进行排序
【发布时间】:2023-03-06 15:29:01
【问题描述】:

我有一套

set(['booklet', '4 sheets', '48 sheets', '12 sheets'])

排序后我希望它看起来像

4 sheets,
12 sheets,
48 sheets,
booklet

有什么建议

【问题讨论】:

    标签: python sorting


    【解决方案1】:

    Jeff Atwood 谈到了自然排序,并举例说明了在 Python 中实现它的一种方法。这是我的变化:

    import re 
    
    def sorted_nicely( l ): 
        """ Sort the given iterable in the way that humans expect.""" 
        convert = lambda text: int(text) if text.isdigit() else text 
        alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
        return sorted(l, key = alphanum_key)
    

    这样使用:

    s = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
    for x in sorted_nicely(s):
        print(x)
    

    输出:

    4 sheets
    12 sheets
    48 sheets
    booklet
    

    这种方法的一个优点是它不仅仅在字符串用空格分隔时起作用。它也适用于其他分隔符,例如版本号中的句点(例如 1.9.1 在 1.10.0 之前)。

    【讨论】:

    • 嗨,杰夫,非常感谢。这正是我想要的。祝你好运。
    • 是否可以根据元组中的第一个值来修改元组列表?示例:[('b', 0), ('0', 1), ('a', 2)] 排序为[('0', 1), ('a', 2), ('b', 0)]
    • 此函数区分大小写。大写字符串将优先。要解决此问题,请在 re.split 中将 .lower() 添加到 key
    • @paragbaxi 在key 之后在alphanum_key lambda 函数中添加[0]lambda key: [ convert(c) for c in re.split('([0-9]+)', key[0]) ]
    【解决方案2】:

    又短又甜:

    sorted(data, key=lambda item: (int(item.partition(' ')[0])
                                   if item[0].isdigit() else float('inf'), item))
    

    这个版本:

    • 适用于 Python 2 和 Python 3,因为:
      • 它不会假设您比较字符串和整数(这在 Python 3 中不起作用)
      • 它不使用cmp 参数到sorted(Python 3 中不存在)
    • 如果数量相等,将按字符串部分排序

    如果您想要完全按照示例中描述的方式打印输出,那么:

    data = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
    r = sorted(data, key=lambda item: (int(item.partition(' ')[0])
                                       if item[0].isdigit() else float('inf'), item))
    print ',\n'.join(r)
    

    【讨论】:

    • 4a sheets 感到窒息,但谁在乎呢?要解决这个问题,您需要一个真正的函数而不是 lambda。
    • 这可能适用于这个简单的例子,但不适用于像 ["1.bla", "2.blub"] 这样的列表。可能拆分应该是一个正则表达式,然后也按第二部分排序,所以 ["1 bcd", "2 abc", "1 xyz"] 正确输出。
    • 不幸的是,@FrankyBoy 是正确的,这不适用于按字母数字对版本号集进行排序;例如,v1.0.1、v3.5.3、v3.2.4
    【解决方案3】:

    您应该查看第三方库natsort。它的算法是通用的,因此它适用于大多数输入。

    >>> import natsort
    >>> your_list = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
    >>> print ',\n'.join(natsort.natsorted(your_list))
    4 sheets,
    12 sheets,
    48 sheets,
    booklet
    

    【讨论】:

      【解决方案4】:

      一种简单的方法是将字符串拆分为数字部分和非数字部分,并使用 python 元组排序顺序对字符串进行排序。

      import re
      tokenize = re.compile(r'(\d+)|(\D+)').findall
      def natural_sortkey(string):          
          return tuple(int(num) if num else alpha for num, alpha in tokenize(string))
      
      sorted(my_set, key=natural_sortkey)
      

      【讨论】:

        【解决方案5】:

        建议我在这里重新发布this answer,因为它也适用于这种情况

        from itertools import groupby
        def keyfunc(s):
            return [int(''.join(g)) if k else ''.join(g) for k, g in groupby(s, str.isdigit)]
        
        sorted(my_list, key=keyfunc)
        

        演示:

        >>> my_set = {'booklet', '4 sheets', '48 sheets', '12 sheets'}
        >>> sorted(my_set, key=keyfunc)
        ['4 sheets', '12 sheets', '48 sheets', 'booklet']
        

        对于 Python3 需要稍微修改一下(这个版本在 Python2 也可以)

        def keyfunc(s):
            return [int(''.join(g)) if k else ''.join(g) for k, g in groupby('\0'+s, str.isdigit)]
        

        【讨论】:

          【解决方案6】:

          对字符串数组中任意位置的任意数字进行排序的通用答案。适用于 Python 2 和 3。

          def alphaNumOrder(string):
             """ Returns all numbers on 5 digits to let sort the string with numeric order.
             Ex: alphaNumOrder("a6b12.125")  ==> "a00006b00012.00125"
             """
             return ''.join([format(int(x), '05d') if x.isdigit()
                             else x for x in re.split(r'(\d+)', string)])
          

          示例:

          s = ['a10b20','a10b1','a3','b1b1','a06b03','a6b2','a6b2c10','a6b2c5']
          s.sort(key=alphaNumOrder)
          s ===> ['a3', 'a6b2', 'a6b2c5', 'a6b2c10', 'a06b03', 'a10b1', 'a10b20', 'b1b1']
          

          部分答案is from there

          【讨论】:

            【解决方案7】:
            >>> a = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
            >>> def ke(s):
                i, sp, _ = s.partition(' ')
                if i.isnumeric():
                    return int(i)
                return float('inf')
            
            >>> sorted(a, key=ke)
            ['4 sheets', '12 sheets', '48 sheets', 'booklet']
            

            【讨论】:

              【解决方案8】:

              根据 SilentGhost 的回答:

              In [4]: a = set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
              
              In [5]: def f(x):
                 ...:     num = x.split(None, 1)[0]
                 ...:     if num.isdigit():
                 ...:         return int(num)
                 ...:     return x
                 ...: 
              
              In [6]: sorted(a, key=f)
              Out[6]: ['4 sheets', '12 sheets', '48 sheets', 'booklet']
              

              【讨论】:

                【解决方案9】:

                集合本质上是无序的。您需要创建一个具有相同内容的列表并对其进行排序。

                【讨论】:

                • 不正确 - 内置的 sorted() 将采用任何序列并返回排序列表。
                • 所以不是创建一个列表并对其进行排序,而是使用一个内置函数来创建一个排序列表....是的,我离题了。
                • 实现了 SortedSets(而不是 HashSets)的集合本质上是 ordered
                【解决方案10】:

                对于那些坚持使用 2.4 之前版本的 Python,没有美妙的 sorted() 函数的人来说,对集合进行排序的快速方法是:

                l = list(yourSet)
                l.sort() 
                

                这并不能回答上面的具体问题(12 sheets 将在 4 sheets 之前出现),但它可能对来自 Google 的人有用。

                【讨论】:

                  【解决方案11】:
                  b = set(['booklet', '10-b40', 'z94 boots', '4 sheets', '48 sheets',
                           '12 sheets', '1 thing', '4a sheets', '4b sheets', '2temptations'])
                  
                  numList = sorted([x for x in b if x.split(' ')[0].isdigit()],
                                   key=lambda x: int(x.split(' ')[0]))
                  
                  alphaList = sorted([x for x in b if not x.split(' ')[0].isdigit()])
                  
                  sortedList = numList + alphaList
                  
                  print(sortedList)
                  
                  Out: ['1 thing',
                        '4 sheets',
                        '12 sheets',
                        '48 sheets',
                        '10-b40',
                        '2temptations',
                        '4a sheets',
                        '4b sheets',
                        'booklet',
                        'z94 boots']
                  

                  【讨论】:

                    猜你喜欢
                    • 2018-04-09
                    • 2019-07-01
                    • 2018-09-03
                    • 2018-05-04
                    • 2011-02-06
                    • 2013-02-09
                    • 1970-01-01
                    • 2013-07-27
                    • 1970-01-01
                    相关资源
                    最近更新 更多