【问题标题】:Sort list with alphabets and numbers in python在python中使用字母和数字对列表进行排序
【发布时间】:2021-12-06 00:33:16
【问题描述】:

请帮我处理列表 我有一个列表名称

arr = [{'name':'cator3'}
       {'name':'cator1'}
       {'name':'CATOR5 (Active A)'},
       {'name':'cator17'},
       {'name':'cator12'},
       {'name':'cator4'},
       {'name':'CATOR5 (Passive A)'},
       {'name':'cator23'},
       {'name':'cator2'}]

每个字典都有一个包含字符和数字的名称。我处理了排序,我得到了结果

我的代码:

def sort_order_by(e):
    order_by = 'name'
    return e[order_by].lower()

sort='asc'

if sort == 'asc':
    arr.sort(key=sort_order_by)
elif sort == 'desc':
     arr.sort(key=sort_order_by, reverse=True)
    
print(arr) 

我的结果:

result = [{'name': 'cator1'},
          {'name': 'cator12'},
          {'name': 'cator17'},
          {'name': 'cator2'},
          {'name': 'cator23'},
          {'name': 'cator3'},
          {'name': 'cator4'},
          {'name': 'CATOR5 (Active A)'},
          {'name': 'CATOR5 (Passive A)'}]

您可以看到初始文本后数字之间的错误排列:

cator1、cator12、cator17、cator2、cator23、cator3 ...

但是 2

希望数字和字母有正确的结果

我期望的结果将按字母和数字顺序排列

expected = [{'name': 'cator1'},
            {'name': 'cator2'},
            {'name': 'cator3'},
            {'name': 'cator4'},
            {'name': 'CATOR5 (Active A)'},
            {'name': 'CATOR5 (Passive A)'},
            {'name': 'cator12'},
            {'name': 'cator17'},
            {'name': 'cator23'},]

如何获得正确的排序顺序?

【问题讨论】:

  • 最通用的解决方案可能是将您的姓名字符串分成单个字符和数字的列表,例如。 ['c','a','t','o','r',12],可以通过遍历字符串并使用 str.isdigit 或 [str.isnumeric] (docs.python.org/3/library/stdtypes.html#str.isnumeric) 并手动排序从那里。也可能有一种方法可以使用正则表达式而不是迭代
  • @AJBiffl。不是单个字符,因为这无济于事:您需要数字和字母区域

标签: python python-3.x list sorting


【解决方案1】:

如果您可以使用外部库,我强烈推荐natsort。运行 pip install natsortconda install natsort 或等效项后,您可以这样做

from natsort import natsorted, ns

arr = natsorted(arr, alg=ns.IGNORECASE, reverse=sort == 'desc')

如果你想要就地排序,你可以生成一个排序键并与arr.sort一起使用:

from natsort import natsort_keygen, ns

arr.sort(key=natsort_keygen(alg=ns.IGNORECASE), reverse=sort == 'desc')

免责声明:我不是 natsort 的作者或与它有任何关联。虽然我确实修复了文档that one time 中的一个小错字。

【讨论】:

  • 谢谢你,但我无法在我的项目中添加新库
  • @TaiDo。这太糟糕了。这是一个很好的图书馆
  • 是的,我知道,但是项目经理将控制库...不是我 :(。谢谢分享,我将在下一个项目中使用它
【解决方案2】:

您可以使用正则表达式替换来右对齐长度为 10 的字符串的数字部分。这将使它们在字符串的字母数字顺序中正确排序(按数字顺序)。

这可以使用 lambda 作为 re.sub() 中的替换值来实现:

arr = [{'name':'cator3'},
       {'name':'cator1'},
       {'name':'CATOR5 (Active A)'},
       {'name':'cator17'},
       {'name':'cator12'},
       {'name':'cator4'},
       {'name':'CATOR5 (Passive A)'},
       {'name':'cator23'},
       {'name':'cator2'}]

import re

arr.sort(key=lambda d: re.sub(r'\d*', 
                              lambda n: f"{n.group():>10}",
                              d['name'].lower()))

print(*arr,sep='\n')
{'name': 'cator1'}
{'name': 'cator2'}
{'name': 'cator3'}
{'name': 'cator4'}
{'name': 'CATOR5 (Active A)'}
{'name': 'CATOR5 (Passive A)'}
{'name': 'cator12'}
{'name': 'cator17'}
{'name': 'cator23'}

如果您要经常在不同的字典列表和/或使用不同的键执行此操作,您可以为其创建一个实用函数:

import re
def alpha_num(k):
    return lambda d: re.sub(r'\d*',lambda n: f"{n.group():>10}",d[k].lower())

arr.sort(key=alpha_num('name'))

【讨论】:

  • 太棒了!!!非常感谢你
【解决方案3】:

下面是一个简短的演示示例,它逐步完成了一个过程。值得注意的是,这是一个任意的排序规范,并没有试图太聪明。

它还假设字符串的长度为 5,后跟一个数字。如果您愿意,可以执行正则表达式或类似过程(或文字迭代)来识别字符串。您还可以更进一步,建立更一般的关系(尽管听起来您并不关心)。

arr=[
    {'name':'cator3'},
    {'name':'cator1'},
    {'name':'CATOR5 (Active A)'},
    {'name':'cator17'},
    {'name':'cator12'},
    {'name':'cator4'},
    {'name':'CATOR5 (Passive A)'},
    {'name':'cator23'},
    {'name':'cator2'}
]

def sort_order_by(e):
    order_by = 'name'
    key = e[order_by].lower()              ; print(key, "->", end=' ')
    split = key.split()
    rest = ' '.join(split[1:])
    key = split[0]                         ; print(key, "->", end=' ')
    key, nkey = key[:5], key[5:]           ; print(key, nkey, "->", end=' ')
    nkey = f"{int(nkey):05}"               ; print(key + nkey + rest)
    return key + nkey + rest

sort_type = 'asc'

arr.sort(key=sort_order_by, reverse=(sort_type == 'desc'))
    
[print(x) for x in arr]

输出:

cator3 -> cator3 -> cator 3 -> cator00003
cator1 -> cator1 -> cator 1 -> cator00001
cator5 (active a) -> cator5 -> cator 5 -> cator00005(active a)
cator17 -> cator17 -> cator 17 -> cator00017
cator12 -> cator12 -> cator 12 -> cator00012
cator4 -> cator4 -> cator 4 -> cator00004
cator5 (passive a) -> cator5 -> cator 5 -> cator00005(passive a)
cator23 -> cator23 -> cator 23 -> cator00023
cator2 -> cator2 -> cator 2 -> cator00002

{'name': 'cator1'}
{'name': 'cator2'}
{'name': 'cator3'}
{'name': 'cator4'}
{'name': 'CATOR5 (Active A)'}
{'name': 'CATOR5 (Passive A)'}
{'name': 'cator12'}
{'name': 'cator17'}
{'name': 'cator23'} 

【讨论】:

  • 这是我需要的好方法。但是如果名字不同呢?
  • 功能齐全,但老实说,这是一种非常糟糕的方法:) 您不必重新组合数字:元组按字典顺序排序。因此,('x', 3)('x', 10) 之类的内容将被正确排序,而无需将整数转换为字符串。
猜你喜欢
  • 2021-04-04
  • 2018-09-03
  • 2020-09-04
  • 2021-05-15
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
相关资源
最近更新 更多