How to sort nested dict based on second value

Question:

I have a dict like this: (More than 1000 records)

{"Device1": [["Device1", "TenGigabitEthernet1/0/12", "SHUT", "", "", "IDF03"], ["Device1", "TenGigabitEthernet1/0/11", "SHUT", "", "", "IDF03", "#f76f6f"]], "Device2": [["Device2", "TenGigabitEthernet1/0/12", "SHUT", "", "", "IDF03"], ["Device2", "TenGigabitEthernet1/0/11", "SHUT", "", "", "IDF03", "#f76f6f"]]}

The problem is, I don’t know how to sort the dict based on the portName which would be TenGigabitEthernet1/0/* or GigabitEthernet1/0/*

I have the following code but it’s not doing it right:

with open("data-dic.txt", 'r') as dic:
    data = dic.read()
    dataDic = json.loads(data)
    dataDic = ast.literal_eval(json.dumps(dataDic))

    d2 = OrderedDict({ k : dataDic[1] for k in natsorted(dataDic) })
    print(d2)

It is sorting the keys which is the Device1, Device2,…

How can I sort the dict based on the second value of the nested dict? which would be all the portNames.

Asked By: user15109593

||

Answers:

You can do this,

with open("data-dic.txt", 'r') as dic:
    data = json.load(dic)
    d2 = OrderedDict(sorted(data.items(), key=lambda x:int(x[1][0][1].rsplit('/', 1)[-1])))
    print(d2)

Sorting based on the value.first_row.second_element.rsplit('/', 1)[-1]

NB:
dataDic = ast.literal_eval(json.dumps(dataDic)) This line of code doing absolutely nothing. You change dict -> str -> dict. And it’s not a good practice to use ast.literal_eval to parse the JSON.

Answered By: Rahul K P

Use a dict comprehension and sort sublist by index.

output = {k: sorted(data.get(k), key=lambda x: x[1].split("/", 2)[-1]) for k in data.keys()}
print(output)

{'Device1': [['Device1', 'TenGigabitEthernet1/0/11', 'SHUT', '', '', 'IDF03', '#f76f6f'], ['Device1', 'TenGigabitEthernet1/0/12', 'SHUT', '', '', 'IDF03']], 'Device2': [['Device2', 'TenGigabitEthernet1/0/11', 'SHUT', '', '', 'IDF03', '#f76f6f'], ['Device2', 'TenGigabitEthernet1/0/12', 'SHUT', '', '', 'IDF03']]}
Answered By: Jason Baker
import pandas as pd
from itertools import chain

header = ['Name', 'Connection', 'Type', 'Col_3', 'Col_4', 'ID', 'Color']

df = pd.DataFrame(chain(*data.values()), columns=header).fillna('')
print(df)

This looks like:

      Name                Connection  Type Col_3 Col_4     ID    Color
0  Device1  TenGigabitEthernet1/0/12  SHUT              IDF03
1  Device1  TenGigabitEthernet1/0/11  SHUT              IDF03  #f76f6f
2  Device2  TenGigabitEthernet1/0/12  SHUT              IDF03
3  Device2  TenGigabitEthernet1/0/11  SHUT              IDF03  #f76f6f

Overkill for this issue… but if you are going to be doing other manipulation of this data, you may want to consider pandas.

df['Port'] = df.Connection.str.extract('.*/(.*)').astype(int)

out = (df.sort_values('Port')
         .drop('Port', axis=1)
         .groupby('Name', sort=False)
         .apply(lambda x: x.apply(list, axis=1).tolist())
         .to_dict())

print(out)

Output:

{'Device1': [['Device1', 'TenGigabitEthernet1/0/11', 'SHUT', '', '', 'IDF03', '#f76f6f'], ['Device1', 'TenGigabitEthernet1/0/12', 'SHUT', '', '', 'IDF03', '']],
 'Device2': [['Device2', 'TenGigabitEthernet1/0/11', 'SHUT', '', '', 'IDF03', '#f76f6f'], ['Device2', 'TenGigabitEthernet1/0/12', 'SHUT', '', '', 'IDF03', '']]}
Answered By: BeRT2me
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.