I want to have a custom sort on a dictionary that I generate in a nested loop. I know that five records will always be there, but there could be others based on the data I go through. I essentially want those five records in a specific order, and then the order does not matter for all records after those five.
For example, I want this:
{"Entries": [], "Groups": [], "Admin": [], "Network": [], "XYZ": [], "Subnets": []}
to be sorted to this:
{"Admin": [], "Groups": [], "Network": [], "Subnets": [], "Entries": [], "XYZ": []}
Therefore, Admin, Groups, Network, Subnets, and Entries are the five that I want in that specific order at the beginning of the dictionary, and after that the remaining entries' order does not matter. How can I do this?
You need collections.OrderedDict for that...
So, based on that, the solution is something like:
def custom_order(dct, spec):
"""
dct - the dictionary
spec - a list of dedicated keys
"""
res = collections.OrderedDict()
dct = dict(dct)
for key in spec:
if key in dct:
res[key] = dct.pop(key)
res.update(dct.items())
return res
You first need to
Here is an example where I sort your data based on the length of the key
>>> from collections import OrderedDict
>>> some_dict = {"Entries": [], "Groups": [], "Admin": [], "Network": [], "XYZ": [], "Subnets": []}
>>> some_dict = OrderedDict(sorted(some_dict.items(),key = lambda e:len(e[0])))
>>> some_dict
OrderedDict([('XYZ', []), ('Admin', []), ('Groups', []), ('Subnets', []), ('Network', []), ('Entries', [])])
将数据存储为成对列表。
I've re-thought out how I approach the entire situation, and found a method that works for me.
With a dataset like the following:
{"Entries": [], "Groups": [], "Admin": [], "Network": [], "XYZ": [], "Subnets": []}
I just do the following, which works fine for me:
for menu in ["Admin", "Groups", "Network", "Subnets", "Entries"]:
try:
doWork(my_dataset[menu])
del my_dataset[menu]
except KeyError:
# The user might not have any entries for that menu, so don't worry about it
pass
for menu in my_dataset.keys():
doWork(my_dataset[menu])
So basically, do what I need to do with the five items and delete them from the dataset. I'm comfortable with doing this, since I'm not using said dataset after this block of code. I don't delete the remaining ones after I do work on them, because that's unnecessary. Garbage collection will just blow away the whole dataset after the function's been completed, right?
I had exactly the same problem and devised a lightweight general solution:
from collections import OrderedDict
def make_custom_sort(orders):
orders = [{k: -i for (i, k) in enumerate(reversed(order), 1)} for order in orders]
def process(stuff):
if isinstance(stuff, dict):
l = [(k, process(v)) for (k, v) in stuff.items()]
keys = set(stuff)
for order in orders:
if keys.issuperset(order):
return OrderedDict(sorted(l, key=lambda x: order.get(x[0], 0)))
return OrderedDict(sorted(l))
if isinstance(stuff, list):
return [process(x) for x in stuff]
return stuff
return process
First, you create an instance of a custom-order sorting function:
custom_sort = make_custom_sort([ ["Admin", "Groups", "Network", "Subnets", "Entries"] ])
Now, the actual sorting:
result = custom_sort(my_dataset)
The missing keys are rejected at the end in an unspecified order. Note that this closure is recursive. As indicated by the double brackets, you could specify as many sort orders as the various dictionaries nested in your structure would require.
Project on GitHub: https://github.com/laowantong/customsort
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.