I'm new to dict structures and I have the following:
d = {'a': 'aa', 'b': 'bb', 'c': 'cc', 'x':111, 'y': 222, 'z':333}
And I want to change to the following structure:
d2 = {'a': 'aa', 'b': 'bb', 'cc':{ 'x':111, 'y': 222, 'z':333}}
Basically, the value
of a given key
will become the key
itself and subsequent values
will go into this new key as a nested dict.The values of x
, y
and z
are demonstrative only, they can be floats or integers. Always after the c
key, will come the values that need to be placed inside c
. Thank you
CodePudding user response:
A tricky solution would be to use pandas.DataFrame
constructor from pandas :
import pandas as pd
def nest_dict(d, val):
v = next((k for k, v in d.items() if v == val), None)
df = pd.DataFrame(d, index=[0])
idx = df.columns.get_loc(v)
out = df.iloc[:, :idx].to_dict("records")[0]
out[val] = df.iloc[:, idx 1:].to_dict("records")[0]
return out
d2 = nest_dict(d1, "cc")
Output :
print(d2)
#{'a': 'aa', 'b': 'bb', 'cc': {'x': 111, 'y': 222, 'z': 333}}
CodePudding user response:
This seems like a vague question and more details regarding the constraints/rules should be provided. However, with the given details, here is a piece of code that should help you out.
import itertools
def slice_dic(dic, k):
keys = list(dic)
lts = keys.index(k)
d = dict(itertools.islice(dic.items(), lts))
d2 = dict(itertools.islice(dic.items(), lts 1,len(keys)))
d[list(dic.values())[lts]] = d2
return d
input_dict = {'a': 'aa', 'b': 'bb', 'c': 'cc', 'x':111, 'y': 222, 'z':333}
slice_dic(input_dict, "c") #slices the dictionary at c
#and keeps all subsequent key:value pairs as a dictinoary
The above snippet gives the following output:
{'a': 'aa', 'b': 'bb', 'cc': {'x': 111, 'y': 222, 'z': 333}}
CodePudding user response:
With limited information present and without using any libraries
def spl_dict(d, pos):
d2 = dict(list(d.items())[:pos-1])
d2[list(d.values())[pos-1]]= dict(list(d.items())[pos:])
return d2
print(spl_dict(d,3))
Output :
{'a': 'aa', 'b': 'bb', 'cc': {'x': 111, 'y': 222, 'z': 333}}
CodePudding user response:
Here is a little longer solution fitted for more general cases:
d = {'a': 'aa', 'b': 'bb', 'c': 'cc', 'x':111, 'y': 222, 'z':333}
slicing_key = 'c'
svalue = d[slicing_key]
d2 = {}
d2[svalue] = {}
# List of all keys
all_keys = list(d.keys())
# Index of the key where you slice
slice_ind = all_keys.index(slicing_key)
# Unchanged entries
orig_keys = all_keys[:slice_ind]
# Keys for entries in the inner dict
new_keys = all_keys[slice_ind 1:]
# Assemble the new dictionary
for key in orig_keys:
d2[key] = d[key]
for key in new_keys:
d2[svalue][key] = d[key]
First you pre-define your output dictionary, then you split up the list of all keys based on your slicing key criterion, and finally you assemble the new dictionary.
Note that this relies on the fact that the list returned by keys()
is ordered. It should be this way now but you can also sort it to be on the safe side, all_keys = list(sorted(d.keys()))
.
CodePudding user response:
Assuming that you hold an insertion order of your input dict, the solution with itertools.groupby
util to get sequential groups counting on c
key:
from itertools import groupby
d = {'a': 'aa', 'b': 'bb', 'c': 'cc', 'x':111, 'y': 222, 'z':333}
head, c, tail = [list(gr) for _, gr in groupby(d.items(), lambda t: t[0] == 'c')]
c_k, c_v = c[0] # for c key
res = {**dict(head), **{c_v: dict(tail)}}
{'a': 'aa', 'b': 'bb', 'cc': {'x': 111, 'y': 222, 'z': 333}}