2013-03-22 158 views
-2

我正在使用csv.DictReader()來讀取文件。它實際上返回一個字典列表,而不是單個字典。我如何強制它返回單個字典,或者如何合併它返回的字典列表?Python:DictReader返回字典列表?

def agilent_e8361c_pna_read(file_loc): 
    ''' 
    Load the '.s2p' file in to a dictionary. 
    ''' 

    with open(file_loc) as f: 
     # define the fields in the Agilent '.s2p' file 
     col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"] 

     # read the data into a dictionary 
     s2p_dicts = csv.DictReader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ') 

    return s2p_dict 

理想情況下,數據將被最初讀成一個單一的字典,從來沒有需要合併。它是一組數據。這些列屬於一起,沒有完整集合或連貫的子集是無意義的。如果DictReader不是「pythonically」能夠完成這個壯舉,我將決定合併詞典列表。這不應該是科學家和程序員都想要用數據集所做的不常見的事情。

+1

爲什麼會返回單個字典?它爲輸入文件中的每一行返回一個字典,這就是它的意圖。 – 2013-03-22 14:21:43

+0

如果你輸入的文件只包含* 1 *行,只需選擇那一行:'return next(s2p_dict)'。 – 2013-03-22 14:23:32

+0

如果它包含多行,您是如何預期數據將被映射到字典的鍵? – 2013-03-22 14:24:27

回答

4

如果你想的key:listOfValues一個字典,你可以做這樣的事情:

def transposeDict(listOfDicts): 
    """Turn a list of dicts into a dict of lists. Assumes all dicts in the list have the exact same keys.""" 

    keys = listOfDicts[0].iterkeys() 
    return dict((key, [d[key] for d in listOfDicts]) for key in keys) 

或者,在python2.7或更高版本:

def transposeDict(listOfDicts): 
    """Turn a list of dicts into a dict of lists. Assumes all dicts in the list have the exact same keys.""" 

    keys = listOfDicts[0].iterkeys() 
    return {key: [d[key] for d in listOfDicts] for key in keys} 

當然,這個假設中的所有類型的字典該列表具有完全相同的密鑰 - 它們將來自DictReader。

一般情況下,如果不是的話,你需要如果你想佔位符缺失值做類似的東西

from collections import defaultdict 

def transposeListOfDicts(listOfDicts): 
    """Turn a list of dict into a dict of lists""" 

    result = defaultdict(list) 

    for d in listofDicts: 
     for key, value in d.iteritems(): 
      result[key].append(item) 

    return result 

,那麼它看起來像這樣:

def transposeListOfDicts(listOfDicts): 
    keys = {} 
    for d in listOfDicts: 
     keys.update(d.iterkeys()) 

    return {key: [d.get(key, None) for d in listOfDicts] for key in keys} 
+0

這是一個非常好的答案。感謝您花時間發佈它! – 2013-03-22 14:57:11

+2

我也許在工作中有點無聊...... – RoadieRich 2013-03-22 14:57:23

2

DictReader將每行都定期csv.reader()返回並根據您傳入或從第一行讀取的字段名將其轉換爲字典。這是設計。

如果您輸入的文件只包含一個行,通過讀取器調用next()返回:

def agilent_e8361c_pna_read(file_loc): 
    with open(file_loc) as f: 
     col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"] 

     reader = csv.DictReader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ') 
     return next(reader) 

請注意,next()調用應該是while塊內,否則文件將被關閉然後才能讀取它。

如果您需要將行合併到一個字典中,則需要聲明您希望如何查看合併的數據。您可以輕鬆地將合併入行每列出重點:

import csv 

def agilent_e8361c_pna_read(file_loc): 
    with open(file_loc) as f: 
     col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"] 
     result = {k: [] for k in col_names} 

     reader = csv.reader(itertools.ifilter(n_input.is_comment, f), fieldnames=col_names, delimiter=' ') 
     for row in reader: 
      for k, v in zip(col_names, row): 
       result[k].append(v) 

     return result 

我們並不需要一個DictReader了在這一點上,因爲我們沒有建立每行一本字典在這裏。

1

好,這是最優雅的解決方案,任何人都有這個問題。

def agilent_e8361c_pna_read(file_loc): 
    ''' 
    Load the '.s2p file in to a dictionary. 
    ''' 

    with open(file_loc) as f: 
     # read the data into a dictionary 
     rows = csv.reader(itertools.ifilter(n_input.is_comment, f), delimiter=' ') 

     # transpose data 
     cols = transpose(rows) 

     # create a dictionary with intuitive key names 
     col_names = ["f","s11","arg_s11","s21","arg_s21","s12","arg_s12","s22","arg_s22"] 
     s2p_dict = dict(zip(col_names,cols)) 

    return s2p_dict 

def transpose(l): 
    return map(list, zip(*l)) 
+0

不能保證'dict'中的項目總是以相同的順序返回(參見http://docs.python.org/2/library/stdtypes.html #dict.items),所以你可以看到列混合起來。 此外,註釋「將列表轉換爲字典」是不準確的,因爲「行」不是「list」的「列表」,並且「transpose()」的返回值是「list」不是'dict'。 – RoadieRich 2013-03-22 15:31:59

+0

@RoadieRich你是對的 - 該評論已經失效。所以你基本上不會想用字典來存儲有序對呢? – 2013-03-22 15:41:45

+0

@RoadieRich其實,如果你所做的只是迭代,順序不會改變。 – 2013-03-22 15:44:02