csv到特定列表中的字典(在重复键时添加值)

时间:2018-05-08 00:52:47

标签: python list dictionary

我有一个像csv:

2018-01-31;1;2;4
2018-01-31;0;3;0
2018-02-01;5;6;7
2018-02-02;8;9;10

我的目标是获得:

mydict = {
2018-01-31: [[1], [2,3], [4]], 
2018-02-01: [[5], [6],   [7]],
2018-03-02: [[8], [9],  [10]]
}

请注意,当存在“重复”键(例如2018-01-31)时,必须将其值添加到该键的先前现有值(示例中为2,3)。 修改:如果可能,我不想添加0。

到目前为止,我能找到的最相似的解决方案是:

from collections import OrderedDict

with open('myfile.csv') as f:
    r = csv.reader(f, delimiter=";")
    od = OrderedDict()
    for row in r:
        # get key/ first element in row
        key = row[0]
    # create key/list paring if it does not exist, else just append the value
    od.setdefault(key, []).append(row[1:])

...哪个结果甚至不是字典。我已经被这件事困住了一段时间,非常感谢你。

PS1:行数/列数可能会有所不同,但总计 - 每行的列数相同

PS2:不幸的是我无法使用Pandas

2 个答案:

答案 0 :(得分:2)

您可以使用itertools.groupbyzip

import itertools, csv
with open('filename.csv') as f:
  data = list(csv.reader(f, delimiter=';'))

new_results = {a:[list(filter(None, map(int, c))) 
   for c in zip(*map(lambda x:x[1:], list(b)))]  
     for a, b in itertools.groupby(sorted(data, key=lambda x:x[0]), key=lambda x:x[0])
}

输出:

{'2018-01-31': [[1], [2, 3], [4]], '2018-02-01': [[5], [6], [7]], '2018-02-02': [[8], [9], [10]]}

答案 1 :(得分:2)

使用循环和zip(),您可以这样做:

代码:

def split_data(some_data):
    results = OrderedDict()
    for datum in some_data:
        split = datum.strip().split(';')
        if split[0] in results:
            for val, dest in zip(split[1:], results[split[0]]):
                if val != '0':
                    dest.append(int(val))
        else:
            results[split[0]] = [[int(s)] for s in split[1:]]
    return results

测试代码:

from collections import OrderedDict

data = """
    2018-01-31;1;2;4
    2018-01-31;0;3;0
    2018-02-01;5;6;7
    2018-02-02;8;9;10
""".split('\n')[1:-1]

print(split_data(data))

结果:

OrderedDict([
    ('2018-01-31', [[1], [2, 3], [4]]), 
    ('2018-02-01', [[5], [6], [7]]), 
    ('2018-02-02', [[8], [9], [10]])
])