2016-09-21 88 views
0

我已經列出了一個由姓氏,姓名,出生日期等排列的csv文件中的大約7000個名字。我還有一個大約7000+個掃描文檔的文件夾註冊表格),其中每個人的名字都是文件名。匹配csv文件中的文件名到文件夾中的文件名

現在,文件名可能與csv中的名稱不完全匹配。 John Doe在csv中的文件名將是John-Michael Doe等。

我該如何編寫一個程序,通過csv查看並查看掃描的文件夾中缺少哪些文件名?

我是一個完全新手編程和任何意見表示讚賞。

+0

看這個的一種方法是製作兩個集合,一個來自csv的(姓名),另一個從文件名中提取(通過拆分等)。除非你有一個一致的命名約定,否則你不會有完整的匹配,但是這應該讓你頭痛得多:) – sal

+0

作爲編程的完全新手,你可能會發現這個教程很有用:https://www.dataquest.io /你需要做一些事情,比如讀取文件夾中的文件名,辨別正則表達式,考慮「bigO」策略來檢查列表等。把它分解成小部分並繼續黑客入侵,祝你好運! –

回答

0

您想要做的第一件事就是將CSV讀取到內存中。你可以用csv module來做到這一點。最有用的工具有csv.DictReader,這需要的文件在字典中鍵的第一行,並讀取餘數爲:

import csv 
with open('/path/to/yourfile.csv', 'r') as f: 
    rows = list(csv.DictReader(f)) 

from pprint import pprint 
pprint(rows[:100]) 

在Windows中,路徑看起來不同,會是這樣的c:/some folder/some other folder/(注意前斜槓而不是反斜槓)。

這將顯示文件的前100行。例如,如果你有一個名爲列「名」,「姓」,「出生日期」,這將是這樣的:

[{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'}, 
{'Date of Birth': 'Jan 1, 1970', 'First Name': 'John', 'Last Name': 'Doe'} 
...] 

接下來,你要得到所有的7000個文件的列表,使用os.listdir

import os 
images_directory = '/path/to/images/' 
image_paths = [ 
    os.path.join(images_directory, filename) 
    for filename in os.listdir(images_directory)] 

現在您需要一些方法從文件中提取名稱。這關鍵取決於文件的結構。這個任務使用棘手的但非常強大的工具稱爲正則表達式,但可能是簡單的東西就足夠了。例如,如果文件被命名爲喜歡「直呼其名的最後name.pdf」,你可以寫一個簡單的分析方法,如:

def parse_filename(filename): 
    name, extension = filename.split('.') 
    first_name, last_name = name.split(' ') 
    return first_name.replace('-', ' '), last_name.replace('-', ' ') 

確切的實施將取決於文件的命名方式,但關鍵的事情,讓你開始是str.split,str.strip和在同一類別的一些其他人。你也可以看看re module for handling regular expressions。正如我所說,這是一種更先進/強大的技術,所以現在可能不值得擔心。

一種簡單的方法做匹配會像下面這樣:

name_to_filename = {parse_filename(filename.lower()): filename for filename in filenames} 
matched_rows = [] 
unmatched_files = [] 
for row in rows: 
    name_key = (row['First Name'].lower(), row['Last Name'].lower()) 
    matching_file = name_to_filename.get(name_key) # This sees if we have a matching file name, and returns 
                # None otherwise. 
    new_row = row.copy() 
    if matching_file: 
     new_row['File'] = matching_file 
     print('Matched "%s" to %s' % (' '.join(name_key), matching_file)) 
    else: 
     new_row['File'] = '' 
     print('No match for "%s"' % (' '.join(name_key))) 
    matched_rows.append(new_row) 
with open('/path/to/output.csv', 'w') as f: 
    writer = csv.DictWriter(f, ['First Name', 'Last Name', 'Date of Birth', 'File]) 
    writer.writeheader() 
    writer.writerows(matched_rows) 

這應該給你什麼你行可以匹配自動匹配起來,其餘的空白輸出電子表格。根據數據的乾淨程度,您可能只能手動匹配剩餘的幾個條目。只有7000人,「愚蠢」的啓發式可能會吸引大部分人。如果您需要更高級的啓發式方法,則可以查看名稱中的「單詞」的Jaccard similarity以及用於近似字符串匹配的difflib模塊。

當然這個代碼大部分不會相當工作在你的問題上,但希望它足以讓你開始。

相關問題