bdrnglm
bdrnglm

Reputation: 143

Get a string list from a word

I'm trying to invert items of a dictionary containing strings as key and string list as value:

dico = {'key1': [],
        'key2': [],
        'key3': ['value1', 'value1'],
        'key4': ['value2', 'value2'],
        'key5': ['value3'],
        'key6': ['value1', 'value2', 'value3']}

new_dict = {}

for key, values in dico.items():
    if values:
        for value in values:
            try:
                if key not in new_dict[value]:
                    new_dict[value].append(key)
            except KeyError:
                new_dict[values[0]] = list(key)
            else:
                print('ERROR')

Here's the result expected:

#Expected
new_dict = {'value1': ['key3', 'key6'],
            'value2': ['key4', 'key6'],
            'value3': ['key5', 'key6']}
#Reality
new_dict = {'value1': ["k", "e", "y", "3", "k", "e", "y", "6"],
            'value2': ["k", "e", "y", "4", "k", "e", "y", "6"],
            'value3': ["k", "e", "y", "5", "k", "e", "y", "6"]}

I noticed if I change that:

new_dict[values[0]] = list(key)

by that:

new_dict[values[0]] = []
new_dict[values[0]].append(key)

It actually works but is there another way to do it in one line ?

Upvotes: 1

Views: 112

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1124768

You are turning your keys to lists:

new_dict[values[0]] = list(key)

That'll produce a list with individual characters. Use a list literal instead:

new_dict[values[0]] = [key]

You can use the dict.setdefault() method to handle missing keys in new_dict to simplify your code. It looks like you want to produce sets instead; sets track unique values and saves you having to do explicit tests for duplicates.

for key, values in dico.items():
    for value in values:
        new_dict.setdefault(value, set()).add(key)

You can always turn those sets back to lists afterwards:

new_dict = {key: list(values) for key, values in new_dict.items()}

Demo:

>>> dico = {'key1': [],
...         'key2': [],
...         'key3': ['value1', 'value1'],
...         'key4': ['value2', 'value2'],
...         'key5': ['value3'],
...         'key6': ['value1', 'value2', 'value3']}
>>> new_dict = {}
>>> for key, values in dico.items():
...     for value in values:
...         new_dict.setdefault(value, set()).add(key)
... 
>>> new_dict
{'value3': set(['key6', 'key5']), 'value2': set(['key6', 'key4']), 'value1': set(['key3', 'key6'])}
>>> {key: list(values) for key, values in new_dict.items()}
{'value3': ['key6', 'key5'], 'value2': ['key6', 'key4'], 'value1': ['key3', 'key6']}

Upvotes: 2

Vivek Sable
Vivek Sable

Reputation: 10223

  1. Iterate every item from main dico dictionary.
  2. Check if value is present or not.
  3. Iterate every item from value.
  4. Use set method to remove duplicate values.
  5. Add to new_dict dictionary where value is key and key is list value.

code:

dico = {'key1': [],
        'key2': [],
        'key3': ['value1', 'value1'],
        'key4': ['value2', 'value2'],
        'key5': ['value3'],
        'key6': ['value1', 'value2', 'value3']}

new_dict = {}

for key, values in dico.items():
    if values:
        for value in set(values):
            try:
                new_dict[value].append(key)
            except:
                new_dict[value] = [key]

import pprint
pprint.pprint(new_dict)

Output:

$ python test.py 
{'value1': ['key3', 'key6'],
 'value2': ['key6', 'key4'],
 'value3': ['key6', 'key5']}

Upvotes: 2

Related Questions