2016-02-28 76 views
0

我有一個大名單列表,其中包含多個名稱的條目用逗號或分號分隔,或者即使偶爾不會。例如:可靠地轉換「最後,第一,最後,第一個」名稱的逗號/分號分隔列表

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 

我試圖創建一個功能,我在每個條目通過單獨,這將可靠地返回一個列表,一切正常有序的「第一個最後」與像JR任何可能的後綴, MD等,到目前爲止,從另一個SO問題,我有:

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 

如果我剝後綴,如 「MD」 第一,不要讓他們,大部分時間他的時間它的工作。例如以一個例子無前綴:

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'] 

另一起案件中,如 「姓,名A.」原來是['First Last']。對於可能是「第一個最後,最後一個」的情況,我不一定介意它是否被逆轉,因爲它更爲罕見,如果需要,我可以在以後修復它們。由於我不確定是否易於分割一次,然後遍歷每個值,並在需要再次分割時添加到列表中,因此我也在分步處理分號和逗號。

+0

你能給一個簡單的例子,說明什麼可行,什麼不可行;真正的和預期的結果? – utdemir

+0

這隻能解決你的問題的第一部分,但如何使用正則表達式來提取帶有後綴的名稱,例如(這是未經測試,根據需要重新排列和修改給定輸入):'(? [AZ] \ [?AZ] \???\ s?(?[AZ] \ w * \ - [AZ]?\ w *)\ ?[AZ]?\ w *)(?:,\ s |)(? Jr \。| M \ .D \。| \。| Ph \ .D |)' – antikantian

回答

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)。當您看到包含空格的標記時,它是第一個中間組合還是第一個組合?這種含糊不清的邏輯將組合令牌組合起來形成一個人的名字。你可以檢查這些標記是否有空白:如果它們有任何分隔符(這將解決#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 
+0

謝謝。我會試一試。期望的輸出是['First Last']。也許用re.split(r'[;,\ s] \ s *',names)分割,然後在重新組合之前重新排序後綴列表中的所有匹配項? – empedocle

+0

@empedocle儘早拆分空白有助於解決某些情況,但它會導致「First Middle」情況出現問題 - 這可能是一個值得權衡的取捨,具體取決於完整數據集的細節。祝你好運! – FMc

相關問題