user3450897
user3450897

Reputation: 3

Inverting a dictionary?

I get this error message:

TypeError: list indices must be integers, not list

Using this code:

def invert_networks_dict(person_to_networks):
    """
    (dict of {str: list of str}) -> dict of {str: list of str})
    """

    networks_to_person = []

    for person in person_to_networks:
        networks = person_to_networks[person]
        networks_to_person[networks] = person

        if not (networks in networks_to_person):
            networks_to_person[networks] = person
        else:
            networks_to_person[networks].append[person]

How can I fix it?

Upvotes: 0

Views: 283

Answers (4)

m.wasowski
m.wasowski

Reputation: 6387

if you want to 'reverse' dictionary d (swap keys and values), with values being list of strings you can:

dict((tuple(val), key) for key, val in d.items())

However, you can do this only if d.values are unique, as keys in new dictionary must be unique.

Explanation: dict() is a built-in that creates dictionary from sequence of pairs (key, value). As with every dictionary, key must be hashable.

Because we want to make values of d new keys, we need to transform them to something hashable - in this case this will be tuple. We can create it from any sequence, including lists that are values of d, with another builtin: tuple().

So what we need are pairs of keys in values from d. We can get them using d.items(). We can make this in easy way using list comprehension, additionally wrapping val in tuple, to make it hashable, so it can be used as key:

[(tuple(val), key) for key, val in d.items())] # that would create list of pairs

But if we pass something to function, we don't need to create list, we can pass similar expression as generator comprehension, so our final code looks like:

result = dict((tuple(val), key) for key, val in d.items())

Upvotes: 1

MoiTux
MoiTux

Reputation: 818

Do you know that a dict as a items function

So instead of that:

networks_to_person = {}

for person in person_to_networks:
    networks = person_to_networks[person]
    networks_to_person[networks] = person

You can do

networks_to_person = {}

for person, networks in person_to_networks.items():
    networks_to_person[networks] = person

Which can also be written as:

networks_to_person = {networks: person for person, networks in person_to_networks.items()}

Upvotes: 0

arshajii
arshajii

Reputation: 129507

networks_to_person = []

This assigns networks_to_person to a list. However, you want it to be a dict:

networks_to_person = dict()  # <--

You can also use {} (empty dict literal), but I prefer dict() because it makes your intent more explicit.


@glglgl brought up a good point in the comments (which I'll restate here for completeness).

networks_to_person[networks].append[person]

You want to call append here, not index it. Therefore, you want:

networks_to_person[networks].append(person)

Lastly, note that you can't have lists as keys to a dictionary. You can convert them to tuples (which can be keys) instead using tuple().

Upvotes: 1

alecxe
alecxe

Reputation: 473873

You should have initialized networks_to_person as dictionary:

networks_to_person = {}

Upvotes: 1

Related Questions