Python Forum
Swap key and value of a dictionary - and sort it - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Swap key and value of a dictionary - and sort it (/thread-30597.html)



Swap key and value of a dictionary - and sort it - Omid - Oct-27-2020

Hello,

The input is this:

Output:
{'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']}
And the output is supposed to be this:
Output:
{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}
Note that values of each key are sorted.

My code is this:

def reverse_dictionary(input_dict):

    my_dict= {}

    for key, value in input_dict.items():
        for string in value:
            my_dict.setdefault(string.lower(), []).append(key.lower())
    
    output_dict={k:v for k,v in sorted(my_dict.items(), key=lambda item:item[1])}

    return output_dict
But this code is not producing the expected result. What am I missing here?


RE: Swap key and value of a dictionary - and sort it - GOTO10 - Oct-27-2020

(Oct-27-2020, 03:24 PM)Omid Wrote: Note that values of each key are sorted.

Perhaps I am missing something, but it appears to me that the values of each key are sorted correctly when I compare the output of your code to the desired output. The only values that can be sorted are those of 'precise' and 'clever', since they are the only keys that have more than one value.

The keys in your returned dictionary are not sorted in the same way as the desired output, but you didn't mention anything about how the keys are to be sorted. For each key in your code's output, the values appear to be the same (and sorted in the same way) as those in the desired output. If I am missing something, please let me know. Think


RE: Swap key and value of a dictionary - and sort it - deanhystad - Oct-28-2020

What you are missing is what determines the order of the output dictionary. I am missing it too. precise and clever are the first two keys. Is that because they have the most values? But why is talented next?

It took me a while to find a combination of conditions to give me the order precise, clever, talented, bright, exact and smart. I counted letters and computed sums of the ordinal values and looked at sorting based on the values and on particular letters in the values. exact and smart were the most difficult for me.
I got precise, clever, talented, bright, smart and exact fairly early. The sorting key is so bizarre looking that I know there has to be something more direct.


RE: Swap key and value of a dictionary - and sort it - DeaD_EyE - Oct-28-2020

It was just the wrong index. Use index 0 if you want to sort by keys and if you use 1, you're sorting by values.

If you sort by keys, you should get this order:
In [45]: sorted("precise clever talented bright smart exact".split())
Out[45]: ['bright', 'clever', 'exact', 'precise', 'smart', 'talented']
For example, you can sort your str also by length:
In [46]: sorted("precise clever talented bright smart exact".split(), key=len)
Out[46]: ['smart', 'exact', 'clever', 'bright', 'precise', 'talented']
Now back to your code:
def reverse_dictionary(input_dict):
    my_dict= {}
    for key, value in input_dict.items():
        for string in value:
            my_dict.setdefault(string.lower(), []).append(key.lower())
    output_dict={k:v for k,v in sorted(my_dict.items(), key=lambda item:item[0])} # not index 1, index 0 is the key
    return output_dict


# first iteration
from operator import itemgetter


def reverse_dictionary(input_dict):
    result = {}
    by_key = itemgetter(0)
    for key, values in input_dict.items():
        for string in values:
            result.setdefault(string.lower(), []).append(key.lower())
    return dict(sorted(result.items(), key=by_key))


# second iteration
from collections import defaultdict
from operator import itemgetter


def reverse_dictionary(input_dict):
    result = defaultdict(list)
    by_key = itemgetter(0)
    for key, values in input_dict.items():
        for string in values:
            result[string.lower()].append(key.lower())
    return dict(sorted(result.items(), key=by_key))


# third iteration
from collections import defaultdict
from operator import itemgetter


def sort_dict_keys(mapping):
    return dict(sorted(result.items(), key=itemgetter(0)))


def reverse_dictionary(input_dict):
    result = defaultdict(list)
    for key, values in input_dict.items():
        for string in values:
            result[string.lower()].append(key.lower())
    return sort_dict_keys(result)
If you have a predefined order, you could use a mapping to int.
Predefined order:
def custom_order(key_value, default=0):
    key, _ = key_value
    key_order = {
        "bright": 1,
        "clever": 2,
        "exact": 100,
        "precise": 3,
        "smart": 4,
        "talented": 5,
    }
    return key_order.get(key, default)
It's not the best example because the dict was defined inside the function.
But I hope it helps to clarify that you can do also custom sort order.


RE: Swap key and value of a dictionary - and sort it - Omid - Oct-28-2020

Dears,

Thank you so much for taking time to reply my question. It appears that the instructions were confusing and my code was indeed correct.

Regards
Omid