3

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

姓名###@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 中这样做最优雅的方法是什么?

4

1 回答 1

7

更好地使用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',))()
于 2013-10-21T20:23:06.043 回答