Python CSV:根据dict映射写行

时间:2012-07-25 19:48:18

标签: python csv dictionary mapping rules

我有一个dict,用于描述我想要应用于CSV文件中每一行的映射。

dict1 = {"key1":["value1", "value2"], "key2":["value3"]}

我的程序应该读取一行,并将特定列中的键映射到dict提供的值。如果每个键只有一个值,那么脚本应该将包含新值的行写入新文件。如果某个键有多个值,那么每个值应该写一个新行。

例如,csvin包含2行。一行有一列,其中key1存在,另一行有key2。在这种情况下,输出文件csvout应包含更多行,而不是csvin,效果为3.其中两行(与key1关联)将完全相同除了一个单一的值

我目前的脚本是:

def convSan(sfin, cfout):
    with open(sfin, "rb") as fin:
        with open(cfout, "wb") as fout:
            csvin = csv.reader(fin)
            csvout = csv.writer(fout, delimiter=",")
            fline = csvin.next()
            csvout.writerow(fline)

        for row in csvin:
            row[25] = dict1[row[25]]
            csvout.writerow(row)

这会生成一个输出文件,其列数与输入文件相同,但会使用正确的新值填充每个字段(某些字段现在是值列表)。

@ sr2222提供的答案适用于简单列表的情况,但我无法在我的特定情况下使用它。

非常感谢帮助。

2 个答案:

答案 0 :(得分:1)

首先:

for index, value in enumerate(list1):
    list1[index] = list2[index]

是一种更简洁的方式来格式化您的第一个循环。但是,这相当于list1 = copy.copy(list2)。我想你要做的是:

normalized_values = ['123', '456']
content = ['a123', '123', 'b456', '789']
for index, value in enumerate(content):
    for normalized_value in normalized_values:
        if normalized_value in value:
            content[index] = normalized_value

这会让你:

content = ['123', '123', '456', '789']

问题更新后编辑:

replacement_map = {'123' : ('a123', '1234'), '456' : ('00456',)}
input = ['123', '456', '234', '123', '789']
output = []
for value in input:
    try:
        output.extend(replacement_map[value])
    except KeyError:
        output.append(value)

try / except相当于:

if value in replacement_map:
    output.extend(replacement_map[value])
else:
    output.append(value)

回应关于如上所述从2个列表构建地图的评论(注意,如果你总是假设list1和list2的长度相同,那么这只会表现正确):

replacement_map = {}
for key, value in zip(list1, list2):
    try:
        replacement_map[key].append(value)
    except KeyError:
        replacement_map[key] = [value]

答案 1 :(得分:0)

对于感兴趣的人,我能够让它像这样工作:

def convSan(sfin, cfout):
    with open(sfin, "rb") as fin:
        with open(cfout, "wb") as fout:
            csvin = csv.reader(fin)
            csvout = csv.writer(fout, delimiter=",")
            fline = csvin.next()
            csvout.writerow(fline)
            buff = []

            for row in csvin:
                dl = ce.dict1200[row[25]]
                if len(dl) == 1:
                    row[25] = dl[0]
                    csvout.writerow(row)
                else:
                    for i in range(len(dl)-1):
                        row[25] = dl[i]
                        csvout.writerow(row)

转换成功,并且根据需要,我的输入文件包含的行数少于输出文件。