How do I return a new dictionary with values that are a list, from the current dictionary?

Viewed 92

Right now, I am having troubles figuring out how to get the following output. 

Desired Output:

 {'Bobby':  [set(), set(), set(), {'movie_2'}, set(),{'movie_1'}], 
  'Carren': [set(), set(), {'movie_4'}, {'movie_2'}, set(), {'movie_1'}],
  'Deric':  [set(), {'movie_1'}, set(), {'movie_2'}, set(),{'movie_3'}],
  'Alec':   [set(), {'movie_1'}, {'movie_3'}, set(), set(), {'movie_4'}] }

The dictionary I am working with:

d = {'movie_1': {('Bobby', 5), ('Carren', 5), ('Alec', 1), ('Deric', 1)},
     'movie_2': {('Carren', 3), ('Deric', 3), ('Bobby', 3)},
     'movie_3': {('Alec', 2), ('Deric', 5)},
     'movie_4': {('Carren', 2), ('Alec', 5)} }

Inside each value, the tuple represents (person, position).

So, with dictionary d, when you look at the key 'movie_1', the first value is ('Bobby', 5).

Then the key, 'movie_1' is placed into the 5th index in the list.

The code I have so far:

I created a list with 6 items of set(), but I am not entirely sure what to do from here to get the desired output.

from collections import defaultdict

d = {
    'movie_1': {('Bobby', 5), ('Carren', 5), ('Alec', 1), ('Deric', 1)},
    'movie_2': {('Carren', 3), ('Deric', 3), ('Bobby', 3)},
    'movie_3': {('Alec', 2), ('Deric', 5)},
    'movie_4': {('Carren', 2), ('Alec', 5)},
}

def new_dict(d):
    le_dict = defaultdict(set)
    values = [set(), set(), set(), set(), set(), set()]
    for key, value in d.items():
        for person_score in value:
            le_dict[person_score[0]].add(key)   
    return le_dict
3 Answers

I would recommend computing the max index directly from your input data rather than hard coding it.

from collections import defaultdict

def setlist(size):
    def gen():
        return [set() for _ in range(size)]
    return gen

def get_max_index(d):
    return max(score for ranking in d.values() for _, score in ranking)

def rearrange(d, max_index=None):
    if max_index is None:
        max_index = get_max_index(d)
    output = defaultdict(setlist(max_index + 1))
    for movie, ranking in d.items():
        for person, score in ranking:
            output[person][score].add(movie)
    return output

Here is an IDEOne link: https://ideone.com/83v6MN

d = {'movie_1': {('Bobby', 5), ('Carren', 5), ('Alec', 1), ('Deric', 1)}, 'movie_2': {('Carren', 3), ('Deric', 3), ('Bobby', 3)}, 'movie_3': {('Alec', 2), ('Deric', 5)}, 'movie_4': {('Carren', 2), ('Alec', 5)} }

def new_dict(d):
    le_dict = {}
    for key, values in d.items():
        for person, score in values:
            if person not in le_dict:
                le_dict[person] = [set(), set(), set(), set(), set(), set()]
            le_dict[person][score].add(key)
    return le_dict

new_dict(d)

The result:

{'Bobby': [set(), set(), set(), {'movie_2'}, set(), {'movie_1'}],
 'Alec': [set(), {'movie_1'}, {'movie_3'}, set(), set(), {'movie_4'}],
 'Carren': [set(), set(), {'movie_4'}, {'movie_2'}, set(), {'movie_1'}],
 'Deric': [set(), {'movie_1'}, set(), {'movie_2'}, set(), {'movie_3'}]}

The insert method of list can be override as below to have generic implementation. There is no need to find max size or hard code it.

from collections import defaultdict

d = {'movie_1': {('Bobby', 5), ('Carren', 5), ('Alec', 1), ('Deric', 1)},
     'movie_2': {('Carren', 3), ('Deric', 3), ('Bobby', 3)}, 'movie_3': {('Alec', 2), ('Deric', 5)},
     'movie_4': {('Carren', 2), ('Alec', 5)}}


class myList(list):

    def insert(self, index, obj):
        if len(self) <= index:
            for i in range(len(self), index):
                self.append(type(obj)())
            self.append(obj)
        else:
            self[index] = obj


def new_dict(d):
    le_dict = {}

    for key, value in d.items():
        for name, index in value:
            if name not in le_dict:
                le_dict[name] = myList()
            le_dict[name].insert(index, set([key]))

    return le_dict


print(new_dict(d))
Related