在从 CSV 文件导入的字典中添加新键值?

Adding new key values in a dictionary that was imported from an CSV file?

抱歉,我无法使用 pandas。

我有一个示例输入 csv 文件,如下所示:

Alfa,Beta,Charlie,Delta,Echo,Foxtrot,Golf,Hotel,India,Juliett,Kilo
A1,B1,C1,D1,E1,F1,G1,H1,I1,J1,K1
A2,B2,C2,D2,E2,F2,G2,H2,I2,J2,K2
A3,B3,C3,D3,E3,F3,G3,H3,I3,J3,K3
A4,B4,C4,D4,E4,F4,G4,H4,I4,J4,K4
A5,B5,C5,D5,E1,F5,G5,H5,I5,J5,K5
A6,B6,C6,D6,E6,F6,G6,H6,I6,J6,K6
A7,B7,C7,D7,E7,F7,G7,H7,I7,J7,K7
A8,B8,C8,D8,E8,F8,G8,H8,I8,J8,K8
A9,B9,C9,D9,E9,F9,G9,H9,I9,J9,K9

那么我的示例代码如下所示:

import csv

fieldnames_dict = {
    'Beta': 'Beta_New',
    'Echo': 'Echo_New',
    'Foxtrot': 'Foxtrot_New_ALL',
    'Hotel': 'Hotel_New',
    'India': 'India_New',
    'Charlie': 'Charlie_New'
}

with open("book1.csv", "r", encoding="utf-8", errors='ignore') as csv_in:
    with open("xtest_file.csv", "w", encoding="utf-8", errors='ignore') as csv_out:
        reader = csv.DictReader(csv_in, delimiter=',', quotechar='"')
        writer = csv.DictWriter(csv_out, delimiter=',', quotechar='"',
                                fieldnames=list(fieldnames_dict.values()))
        writer.writeheader()
        for row_in in reader:
            row_out = {new: row_in[old] for old, new in fieldnames_dict.items()}
            writer.writerow(row_out)

所以输出 csv 应该是这样的:

Beta_New,Echo_New,Foxtrot_New_ALL,Tango,Victor,Hotel_New,India_New,Charlie_New
B1,E1,F1,T1,V1,H1,I1,C1
B2,E2,F2,T1,V1,H2,I2,C2
B3,E3,F3,T1,V1,H3,I3,C3
B4,E4,F4,T1,V1,H4,I4,C4
B5,E5,F5,T1,V1,H5,I5,C5
B6,E6,F6,T1,V1,H6,I6,C6
B7,E7,F7,T1,V1,H7,I7,C7
B8,E8,F8,T1,V1,H8,I8,C8
B9,E9,F9,T1,V1,H9,I9,C9

因此字典中的所有键都必须是唯一的(所以在 fieldnames_dict 中添加两个空字符串键是不可能的)。也就是说,fieldnames_dict 中的所有键必须已经存在于输入 CSV 文件中,因为字典理解 {new: row_in[old] for old, new in fieldnames_dict.items()} 中的 row_in[old]。这意味着我将不得不 append/add 最后添加新键,但是 如何添加键“Tango,Victor”以及“Foxtrot_New_ALL”和“[=”之间的值31=]"?

我觉得你误解了 DictWriter 的工作原理。

当您指定 fieldnames=... 时,DictWriter 不关心 这些字段名称来自何处,只要它是字符串列表即可。

当你将一个字典传递给 writerow() 时,DictWriter 会查看你之前给它的 fieldnames 来决定从那个字典到 select 的哪些键,以及顺序。

所以重要的是

  1. fieldnames 是一个列名列表,按照您希望列在输出文件中的顺序排列。
  2. 您传递给 writerow 的任何字典都包含 fieldnames 中指定的所有字段。列顺序由 fieldnames 指定,因此此字典的键顺序无关紧要。

考虑到这一点,您可以创建一个包含新列名称的列表,该列表与告诉您旧列如何重命名的字典分开

fields = ['Beta_New',
 'Echo_New',
 'Foxtrot_New_ALL',
 'Tango',
 'Victor',
 'Hotel_New',
 'India_New',
 'Charlie_New']

column_rename_dict = {
    'Beta': 'Beta_New',
    'Echo': 'Echo_New',
    'Foxtrot': 'Foxtrot_New_ALL',
    'Hotel': 'Hotel_New',
    'India': 'India_New',
    'Charlie': 'Charlie_New'
}

然后,您使用 fields 作为您编写器的 fieldnames 参数,并确保您传递给它的任何字典都包含所有这些字段名称。

ctr = 1

with open(...) as csv_in, open(...) as csv_out:
    reader = csv.DictReader(csv_in)
    writer = csv.DictWriter(csv_out, fieldnames=fields)
    writer.writeheader()
    for row_in in reader:
        # Convert the old field names to new field names
        row_out = {new: row_in[old] for old, new in column_rename_dict.items()}

        # Set values for extra keys
        row_out["Tango"] = f"T{ctr}"
        row_out["Victor"] = f"V{ctr}"
        ctr += 1
        
        # Write the row
        writer.writerow(row_out)

这会为您提供新的 csv:

Beta_New,Echo_New,Foxtrot_New_ALL,Tango,Victor,Hotel_New,India_New,Charlie_New
B1,E1,F1,T1,V1,H1,I1,C1
B2,E2,F2,T2,V2,H2,I2,C2
B3,E3,F3,T3,V3,H3,I3,C3
B4,E4,F4,T4,V4,H4,I4,C4
B5,E1,F5,T5,V5,H5,I5,C5
B6,E6,F6,T6,V6,H6,I6,C6
B7,E7,F7,T7,V7,H7,I7,C7
B8,E8,F8,T8,V8,H8,I8,C8
B9,E9,F9,T9,V9,H9,I9,C9