使用Python中的正则表达式对列表进行排序

use*_*528 3 python lambda

我有一个电子邮件地址列表,格式如下:

name###@email.com

但这个数字并不总是存在.例如:john45 @ email.com,bob @email.com joe2@email.com等.我想用数字对这些名字进行排序,没有数字的那些名字先排序.我想出了一些有用的东西,但对Python来说是新手,我很好奇是否有更好的方法.这是我的解决方案:

import re

def sortKey(name):
    m = re.search(r'(\d+)@', name)
    return int(m.expand(r'\1')) if m is not None else 0

names = [ ... a list of emails ... ]
for name in sorted(names, key = sortKey):
    print name
Run Code Online (Sandbox Code Playgroud)

这是我的脚本中唯一一次使用"sortKey",所以我更喜欢它是一个lambda函数,但我不知道该怎么做.我知道这会奏效:

for name in sorted(names, key = lambda n: int(re.search(r'(\d+)@', n).expand(r'\1')) if re.search(r'(\d+)@', n) is not None else 0):
    print name
Run Code Online (Sandbox Code Playgroud)

但我认为我不应该两次调用re.search来做到这一点.在Python中执行此操作的最优雅方式是什么?

Jon*_*nts 5

更好地使用re.findall,好像没有找到数字,然后它返回一个空列表,它将在填充列表之前排序.用于排序的密钥是找到的任何数字(转换为整数),后跟字符串本身......

emails = 'john45@email.com bob@email.com joe2@email.com'.split()

import re
print sorted(emails, key=lambda L: (map(int, re.findall('(\d+)@', L)), L))
# ['bob@email.com', 'joe2@email.com', 'john45@email.com']
Run Code Online (Sandbox Code Playgroud)

而使用john1输出是:['bob@email.com', 'john1@email.com', 'joe2@email.com']这表明虽然在joe之后按字典顺序排列,但是这个数字首先被考虑在内john.

如果你想保持现有的使用re.search的方法在一个单线程中(但是很糟糕),有一种有点hackish的方式:

getattr(re.search('(\d+)@', s), 'groups', lambda: ('0',))()
Run Code Online (Sandbox Code Playgroud)