Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rearrange an Ordered Dictionary with a based on part of the key from a list

Tags:

python

I am rearranging some Ordered Dictionary based on the key from a list. Such in:

old_OD = OrderedDict([('cat_1',1), 
            ('dog_1',2), 
            ('cat_2',3),
            ('fish_1',4), 
            ('dog_2',5)])

Now I have a list of the group's order.

order = ['dog', 'cat', 'fish']

and get the result with the items in the dictionary grouped together, as such:

new_OD = OrderedDict([('dog_1',2),
            ('dog_2',5), 
            ('cat_1',1), 
            ('cat_2',3),
            ('fish_1',4)])

I found some excellent related question How to reorder OD based on list and Re-ordering OrderedDict and I am going with the solution in the second link

new_od = OrderedDict([(k, None) for k in order if k in old_od])
new_od.update(old_od)

Now, in my case, "k" is not exact match and desired key value for the new_od, how should I modify to construct the new od?

EDIT: So what happen if there is no underscore that mark the location of the keyword, like we have "Big_cat_3" or "dog_black_2"? The keyword could be anywhere in the string. Once the key are grouped together, alpha-numerical order is not needed.

like image 795
Bogdan Avatar asked Mar 26 '19 20:03

Bogdan


People also ask

How do you rearrange a dictionary in Python?

To sort a dictionary by value in Python you can use the sorted() function. Python's sorted() function can be used to sort dictionaries by key, which allows for a custom sorting method. sorted() takes three arguments: object, key, and reverse . Dictionaries are unordered data structures.

How do I change the order of my dictionary?

OrderedDicts are ordered by insertion order. So you would have to construct a new OrderedDict by looping over the key:value pairs in the original object. There is no OrderedDict method that will help you.

Can you sort an ordered dict?

Dicts can't be sorted, but you can build a sorted list from them.


1 Answers

Here I am sharing two variants of solution for this.

1. For keys with same prefix, keep the order of initial OrderedDict

Here I am using list comprehension to iterate the order list and OrderDict. Based on comparison, we are passing list of tuples with desired order for creating OrderedDict object:

>>> from collections import OrderedDict
>>> old_OD = OrderedDict([('cat_1',1),
...             ('dog_1',2),
...             ('cat_2',3),
...             ('fish_1',4),
...             ('dog_2',5)])
>>> order = ['dog', 'cat', 'fish']

>>> new_OD = OrderedDict([(k,v) for o in order for k, v in old_OD.items() if k.startswith(o+'_')])
#                                              to match the prefix pattern of <key> + "_" ^ 

where new_OD will hold:

OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])

2. For keys with same prefix, perform lexicographical sorting of elements

We may modify the above solution using sorted and itertools.chain with nested list comprehension to achieve this as:

>>> from itertools import chain

>>> new_OD = OrderedDict(chain(*[sorted([(k,v) for k, v in old_OD.items() if k.startswith(o+'_')]) for o in order]))

where new_OD will hold:

OrderedDict([('dog_1', 2), ('dog_2', 5), ('cat_1', 1), ('cat_2', 3), ('fish_1', 4)])
like image 142
Moinuddin Quadri Avatar answered Oct 26 '22 23:10

Moinuddin Quadri