可靠地转换逗号/分号分隔的“last,first,last,first”名称列表

时间:2016-02-28 22:52:38

标签: python

我有一个很大的名字列表,其中包含多个名称的条目用逗号或分号分隔,甚至偶尔也没有。例如:

First Last
Last, First
Last, First, A.
Last, First Middle
Last, First, Last, First A., Last, First, Ph.D, Last, First, M.D., Last, J. R, Last, O.
Last, First Middle plus other names, Last, First, Jr., Last, First, Sr.
Last, First; Last, First A.; Last, First Middle 
First Last, First Last, First A. Last, Last, First

我正在尝试创建一个函数,因为我单独传入每个条目,这将可靠地返回一个列表,所有正确排序为“First Last”的任何可能的后缀,如Jr,MD等。到目前为止,从另一个问题来看,我有:

def fix_names(names):
    if ',' in names:
        names = [b.strip() + ' ' + a.strip()
                   for a, b in zip(*[iter(names.split(','))] * 2)]
    return names

我想结束:

['First Last']
['First Last', 'First A. Last', 'First Last, Ph.D', 'First Last, Jr.'] etc

如果我首先删除诸如“,M.D”之类的后缀而不保留它们,那么大部分时间它都有效。例如,举一个没有前缀的例子:

Last, First, Last, First A., Last, First, Last, First, Last, J. R., Last, O.

我明白了:

['First Last', 'First A. Last', 'First Last', 'First Last', 'J. R. Last', 'O. Last']

另一个案例,例如“Last,First A.”结果是['First Last']。对于可能是“最后一个,最后一个”的情况,我不一定介意它是否已经反转,因为它更为罕见,如果需要我可以在以后修复它们。我也在不同的步骤中处理分号和逗号,因为我不确定它是否易于拆分一次,然后遍历每个值,并且如果再次需要拆分则添加到列表中。

1 个答案:

答案 0 :(得分:0)

这是一个很难解析的问题,但这里的草图相当不错。

import sys
import re

SUFFIXES = set('''
    Ph.D
    M.D.
    Jr.
    Sr.
'''.split())

regexes = dict(
    punct  = re.compile(r'\s*[;,]\s*'),
    space  = re.compile(r'\s*'),
    middle = re.compile(r'^[A-Z]\.?$'),
)

def main(file_path):
    with open(file_path) as fh:
        for line in fh:
            for name in parse_line(line):
                print name

def parse_line(line):
    tokens = get_tokens(line.strip())
    name = []
    for t in tokens:
        if t in SUFFIXES:
            name.append(t)
        elif regexes['middle'].search(t):
            name.append(t)
        elif len(name) > 1:
            yield name
            name = [t]
        else:
            name.append(t)
    if name:
        yield name

def get_tokens(line):
    k = 'punct' if (';' in line or ',' in line) else 'space'
    return regexes[k].split(line.strip())

main(sys.argv[1])

结果并不完美。目前尚不清楚如何在不在算法中构建更多名称智能的情况下区分下面三个问题案例(#1,#2和#3)。当您看到包含空格的令牌时,它是FIRST-MIDDLE组合还是FIRST-LAST组合?这种模棱两可的态度使得将一起组合起来形成一个人的名字的逻辑绊倒了。你可以检查空格的标记:如果它们有任何,那就分开(这将解决#2和#3),但它会使#1更糟。

['First', 'Last']
['Last', 'First']
['Last', 'First', 'A.']
['Last', 'First Middle']
['Last', 'First']
['Last', 'First A.']
['Last', 'First', 'Ph.D']
['Last', 'First', 'M.D.']
['Last', 'J. R']
['Last', 'O.']
['Last', 'First Middle plus other names']    # 1
['Last', 'First', 'Jr.']
['Last', 'First Sr.']
['Last', 'First']
['Last', 'First A.']
['Last', 'First Middle']
['First Last', 'First Last']                 # 2
['First A. Last', 'Last']
['First']                                    # 3