Home > Net >  Python Sorting in a List of Dictionaries by Numbers
Python Sorting in a List of Dictionaries by Numbers

Time:06-22

I have a list of dictionaries that I'm trying to sort. This is what I have so far:

output_list = [{'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
               {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
               {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'},
               {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
               {'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'}]

mac_list = sorted(output_list, key=lambda d: d['interface'])

pprint(mac_list)

However, it's not sorting the dictionaries the way I want.

"C:\Program Files\Python310\python.exe" "C:/Scripts/Python/test1.py"
[{'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
 {'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
 {'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'},
 {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'},
 {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'}]

Process finished with exit code 0

How can I get it to sort it so it looks like this:

[{'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'},
 {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
 {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
 {'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
 {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'}]

CodePudding user response:

Try this:

mac_list = sorted(output_list, key=lambda d: int(d['interface'].split("/")[1]))

If interface values could start with something other than 0, and you want it to be part of the sorted value, then you could use something like:

mac_list = sorted(output_list, key=lambda d: int(d['interface'].split("/")[0]) * 10000   int(d['interface'].split("/")[1]))

CodePudding user response:

I am not sure if the first number of interface can be more than zero but if not this change helps. You want to only check the number after /:

mac_list = sorted(output_list, key=lambda d: int(d["interface"][2:]))

output is:

[{'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'}, {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'}, {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'}, {'interface': '0/20', 'mac': '01:23:45:67:89:AB'}, {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'}]

CodePudding user response:

If you always have 0/???. Try this:

mac_list  = sorted(output_list, key= lambda x: int(x['interface'][2:]))

Output:

[{'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'},
 {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
 {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
 {'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
 {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'}]

If maybe have ???/???. try this: (How about convert 1/3 to 1.3?)

# 1/3 -> 1.3 then get as float and sort
sorted(output_list, key= lambda x: float(x['interface'].replace('/', '.')))

# or as string
sorted(output_list, key= lambda x: (int(x['interface'][:1]),int(x['interface'][2:])))

Output:

[{'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
 {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
 {'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
 {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'},
 {'interface': '1/3', 'mac': '45:67:89:AB:CD:EF'}]

CodePudding user response:

You need to get the number out of the string:

sorted(output_list, key=lambda d: int(d['interface'].split("/")[1]))

This assumes that the first part of the interface won't change.

If it changes, you need to reformat both parts with the leading zero:

sorted(output_list, key=lambda d: "/".join([f"{int(x):02d}" for x in d['interface'].split("/")]))

CodePudding user response:

Use natsort for natural sorting:

from natsort import natsorted

mac_list = natsorted(output_list, key=lambda d: d['interface'])

Or split and convert to integers:

mac_list = sorted(output_list,
                  key=lambda d: tuple(map(int, d['interface'].split('/'))))

output:

[{'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'},
 {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
 {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
 {'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
 {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'}]

CodePudding user response:

Rather than having a cumbersome looking lambda expression as the key argument, it might be clearer to have a separate function to handle to tuple construction:-

output_list = [{'interface': '0/20', 'mac': '01:23:45:67:89:AB'},
               {'interface': '0/16', 'mac': '12:34:56:78:9A:BC'},
               {'interface': '0/31', 'mac': '23:45:67:89:AB:CD'},
               {'interface': '0/5', 'mac': '34:56:78:9A:BC:DE'},
               {'interface': '0/3', 'mac': '45:67:89:AB:CD:EF'}]

def mt(s):
    return tuple(map(int, s['interface'].split('/')))

mac_list = sorted(output_list, key=mt)

print(mac_list)
  • Related