user4115543
user4115543

Reputation:

Adding list in form of tuples to a dictionary

Assuming there is a list with sublists like this

[[2013, 'Patric', 'M', 1356], [2013, 'Helena', 'F', 202], [2013, 'Patric', 'F', 6],[1993, 'Patric', 'F', 7]......]

which is an output of def list_of_names() where 2013 is year, M is gender and 1356 is number of M births etc.

And I want to create a dictionary which outputs the name as a key and values as tuples (year, number_of_males,number_of_females) . So for example:

{ .. ’Patric’:[... , (1993, 0, 7), (2013, 1356, 6), ... ], ... }.

Technically 1993 is year, 0 is number of males and 7 is number of females and the tuples should be arranged in order of the years.

and I'm stuck on how to add this info into a dictionary

def name_Index(names):
    d = dict()
    L = readNames() #the list with from previous def which outputs different names and info as above
    newlist = []
    for sublist in L:

Upvotes: 1

Views: 100

Answers (4)

sujoy
sujoy

Reputation: 135

I didn't understand why you are taking names as an argument of name_Index function and then calling readNames, there must be some necessity required for your work. Hence, i just put a dummy readNames function and sent None as argument to name_Index. Using class is a good technique to solve complicated data structures. Btw, nicely written question i must admit.

def readNames ():
    return [[2013, 'Patric', 'M', 1356], [2013, 'Helena', 'F', 202], [2013, 'Patric', 'F', 6],[1993, 'Patric', 'F', 7]]

class YearOb(object):
    def __init__(self): 
        self.male = 0
        self.female = 0

    def add_birth_data(self, gender, birth_count):
        if gender == "M":
            self.male += birth_count
        else:
            self.female += birth_count

class NameOb(object):
    def __init__(self):
        self.yearobs = dict()

    def add_record(self, year, gender, birth_count):
        if year not in self.yearobs:
            self.yearobs[year]=YearOb()

        self.yearobs[year].add_birth_data(gender, birth_count)           

    def get_as_list(self):
        list_data = []
        for year, yearob in self.yearobs.items():
            list_data.append((year, yearob.male, yearob.female))
        return list_data

def name_Index(names):
    d = dict()
    L = readNames() #the list with from previous def which outputs different names and info as above
    newlist = []
    for sublist in L:
        name = sublist[1]
        if name not in d:
            d[name]=NameOb()
        d[name].add_record(sublist[0], sublist[2], sublist[3])

    for name, nameob in d.items():
        d[name] = nameob.get_as_list() 

    return d 


print(name_Index(None))

Upvotes: 0

m.wasowski
m.wasowski

Reputation: 6387

The most convenient will be to use collections.defauldict. It returns dictionary-like object, that returns default value, if it doesn't find key. In your case, you use a list as default value, and in your loop you append tuples to it:

from collections import defaultdict

names = [ [2013, 'Patric', 'M', 1356], 
        [2013, 'Helena', 'F', 202], 
        [2013, 'Patric', 'F', 6],
        [1993, 'Patric', 'F', 7]    ]

def name_Index(data):
    # name => year => sex
    d = defaultdict(lambda: defaultdict(lambda: {'F': 0, 'M': 0})) 
    for year, name, sex, births in data:
        d[name][year][sex] += births

    # if you are fine with defauldict result: return d
    # else collect results into tuples:

    result = {}
    for name, data in d.items():
        result[name] = [(year, c['M'], c['F']) for year, c in data.items()]
    return result

    print name_Index(names)
    # {'Helena': [(2013, 0, 202)], 'Patric': [(1993, 0, 7), (2013, 1356, 6)]}

Upvotes: 0

Nafiul Islam
Nafiul Islam

Reputation: 82470

This was my attempt at the problem:

from collections import defaultdict, namedtuple
from itertools import groupby

data = [[2013, 'Patric', 'M', 1356],
        [2013, 'Helena', 'F', 202],
        [2013, 'Patric', 'F', 6],
        [1993, 'Patric', 'F', 7]]

names = defaultdict(list)
datum = namedtuple('datum', 'year gender number')
for k, g in groupby(data, key=lambda x: x[1]):
    for l in g:
        year, name, gender, number = l
        names[k].append(datum(year, gender, number))

final_dict = defaultdict(list)
for n in names:
    for k, g in groupby(names[n], lambda x: x.year):
        males = 0
        females = 0
        for l in g:
            if l.gender == 'M':
                males += l.number
            elif l.gender == 'F':
                females += l.number
        final_dict[n].append((k, males, females))

print(final_dict)

Upvotes: 1

jacg
jacg

Reputation: 2120

from collections import defaultdict

def list_of_names():
    return [[2013, 'Patric', 'M', 1356],
            [2013, 'Helena', 'F', 202],
            [2013, 'Patric', 'F', 6],
            [1993, 'Patric', 'F', 7]]

def name_Index():
    tmp = defaultdict(lambda:defaultdict(lambda: [0,0]))

    for year, name, sex, N in list_of_names():
        i = 0 if sex == 'M' else 1
        tmp[name][year][i] += N

    d = {}
    for name, entries in tmp.items():
        d[name] = [(year, M, F) for (year, (M,F)) in entries.items()]

    return d

print name_Index()

Upvotes: 1

Related Questions