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

时间:2013-10-21 20:15:48

标签: python lambda

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

### @ 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

这是我脚本中唯一一次使用“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

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

1 个答案:

答案 0 :(得分: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']

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

如果您希望保留现有的使用re.search的方法(但是很糟糕),那么有一种不太常见的方式:

getattr(re.search('(\d+)@', s), 'groups', lambda: ('0',))()