You can use defaultdict here. multi need not be sorted.
from collections import defaultdict
out=defaultdict(dict)
for v,k,vs in multi:
out[k]={**out[k],**{v:vs[0]}}
Output
defaultdict(dict,
{77766: {14: 2, 15: 1},
88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3},
99966: {79: 1, 80: 2}})
EDIT:
Sorting the inner dictionaries.
out={k:dict(sorted(v.items(),key=lambda x:x[1])) for k,v in out.items()}
Output:
{77766: {15: 1, 14: 2},
88866: {70: 1, 71: 2, 74: 3, 73: 4, 72: 5},
99966: {79: 1, 80: 2}}
Answer from Ch3steR on Stack OverflowVideos
You can use defaultdict here. multi need not be sorted.
from collections import defaultdict
out=defaultdict(dict)
for v,k,vs in multi:
out[k]={**out[k],**{v:vs[0]}}
Output
defaultdict(dict,
{77766: {14: 2, 15: 1},
88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3},
99966: {79: 1, 80: 2}})
EDIT:
Sorting the inner dictionaries.
out={k:dict(sorted(v.items(),key=lambda x:x[1])) for k,v in out.items()}
Output:
{77766: {15: 1, 14: 2},
88866: {70: 1, 71: 2, 74: 3, 73: 4, 72: 5},
99966: {79: 1, 80: 2}}
Assuming your input list is sorted by the second column, you can use itertools.groupby:
import itertools
multi = [
[14, 77766, [2, 2]],
[15, 77766, [1, 2]],
[70, 88866, [1, 5]],
[71, 88866, [2, 5]],
[72, 88866, [5, 5]],
[73, 88866, [4, 5]],
[74, 88866, [3, 5]],
[79, 99966, [1, 2]],
[80, 99966, [2, 2]],
]
nested = {
key: {l[0]: l[2][0] for l in lines}
for key, lines in itertools.groupby(multi, lambda p: p[1])
}
outputs
{77766: {14: 2, 15: 1},
88866: {70: 1, 71: 2, 72: 5, 73: 4, 74: 3},
99966: {79: 1, 80: 2}}
A nested dict is a dictionary within a dictionary. A very simple thing.
Copy>>> d = {}
>>> d['dict1'] = {}
>>> d['dict1']['innerkey'] = 'value'
>>> d['dict1']['innerkey2'] = 'value2'
>>> d
{'dict1': {'innerkey': 'value', 'innerkey2': 'value2'}}
You can also use a defaultdict from the collections package to facilitate creating nested dictionaries.
Copy>>> import collections
>>> d = collections.defaultdict(dict)
>>> d['dict1']['innerkey'] = 'value'
>>> d # currently a defaultdict type
defaultdict(<type 'dict'>, {'dict1': {'innerkey': 'value'}})
>>> dict(d) # but is exactly like a normal dictionary.
{'dict1': {'innerkey': 'value'}}
You can populate that however you want.
I would recommend in your code something like the following:
Copyd = {} # can use defaultdict(dict) instead
for row in file_map:
# derive row key from something
# when using defaultdict, we can skip the next step creating a dictionary on row_key
d[row_key] = {}
for idx, col in enumerate(row):
d[row_key][idx] = col
According to your comment:
may be above code is confusing the question. My problem in nutshell: I have 2 files a.csv b.csv, a.csv has 4 columns i j k l, b.csv also has these columns. i is kind of key columns for these csvs'. j k l column is empty in a.csv but populated in b.csv. I want to map values of j k l columns using 'i` as key column from b.csv to a.csv file
My suggestion would be something like this (without using defaultdict):
Copya_file = "path/to/a.csv"
b_file = "path/to/b.csv"
# read from file a.csv
with open(a_file) as f:
# skip headers
f.next()
# get first colum as keys
keys = (line.split(',')[0] for line in f)
# create empty dictionary:
d = {}
# read from file b.csv
with open(b_file) as f:
# gather headers except first key header
headers = f.next().split(',')[1:]
# iterate lines
for line in f:
# gather the colums
cols = line.strip().split(',')
# check to make sure this key should be mapped.
if cols[0] not in keys:
continue
# add key to dict
d[cols[0]] = dict(
# inner keys are the header names, values are columns
(headers[idx], v) for idx, v in enumerate(cols[1:]))
Please note though, that for parsing csv files there is a csv module.
UPDATE: For an arbitrary length of a nested dictionary, go to this answer.
Use the defaultdict function from the collections.
High performance: "if key not in dict" is very expensive when the data set is large.
Low maintenance: make the code more readable and can be easily extended.
Copyfrom collections import defaultdict
target_dict = defaultdict(dict)
target_dict[key1][key2] = val