Occurence of name in dictionary

Viewed 50

The situation is as follows: we extracted data from a .txt file with names, children etc. and extracted it into a dictionary. The dictionary is accessed with the name as the key, e.g:

# access a single person in allPersons via the name as key
p1 = allPersons['jan']
print("Name:", p1.name)
print("Sex:", p1.sex)
print("Children:")
for p in p1.children:
    print(p.name)

with the output being:

Name: jan
Sex: female
Children:
marko
anna15

So far so good, but now I am expected to write a function called count which stores the name. So for example 'stefan' as the key and the number of occurrences as the value for the key, while ignoring numeric suffixes to the name such as 'stefan02' or 'stefan10' and to be honest I am really lost on this.

def count(persons):
    name_counts = {}
    # YOUR CODE HERE
    raise NotImplementedError()
    return name_counts
assert count(allPersons)['stefan'] == 20

I tried messing around with code I found online and imports such as regex but honestly I got even more confused than before and I was hoping I could get some pointers in the right direction. This is what I have so far:

def count(persons):
    name_counts = {}
    for j in persons:
        if j in name_counts:
            name_counts[j].name+=1
        else:
            name_counts[j].name=0
    return name_counts

The error I get is 'nora11' which is the first name to be fed from the .txt into the dictionary as context.

3 Answers
occu = {}
for p in persons:
    for i,k in enumerate(p):
        if k.isdigit():
            p = p[:i]
    if p in occu:
        occu[p] += 1
    else:
        occu[p] = 1

Hope this helps

edit: this doesn't work if the digits are not at the end of the name, eg

tom    --> tom
tom123 --> tom
to123m --> to
123tom --> 

IIUC, your allPersons dict looks something like this -

{'jan': {'name': 'jan', 'sex': 'f', 'children': ['a', 'b', 'c']},
 'jan01': {'name': 'jan01', 'sex': 'f', 'children': ['a', 'b', 'c']},
 'jan02': {'name': 'jan02', 'sex': 'f', 'children': ['a', 'b', 'c']}, 
'stefan22': {'name': 'jan02', 'sex': 'm', 'children': ['a', 'b', 'c']}}

Out of this - you want to create an output that looks like - {'jan': 3}

You can try something like this -

from collections import Counter
normalized_keys = [''.join(_ for _ in k if _.isalpha()) for k in allPersons.keys()]
counter_normalized_keys = Counter(normalized_keys)
print(counter_normalized_keys)
# Counter({'jan': 3, 'stefan': 1})

This way of cleaning the keys (using .isalpha() only works for simple cases - depending on the type of variation you see in the data, you might have to switch out the isalpha() method with something more complex, possibly involving regexes.

There's an accepted answer but posting this anyway. Certain assumptions made about a "person" class:

from collections import Counter
from string import digits

def count(persons):
    counter = Counter()
    for k in persons:
        counter[k.rstrip(digits)] += 1
    return counter

class Person:
    def __init__(self, name, sex, children=[]):
        self._name = name
        self._sex = sex
        self._children = children
    def add_child(self, child):
        assert isinstance(child, type(self))
        self.children.append(child)
    @property
    def name(self):
        return self._name
    @property
    def sex(self):
        return self._sex
    @property
    def children(self):
        return self._children
    def __repr__(self):
        return f'Name={self.name}, Sex={self.sex}, Children={",".join(self.children)}'

pdict = {}

N = 20

# add N instances of each of three persons
for np in 'Jim', 'James', 'George':
    for i in range(1, N+1):
        name = f'{np}{i}'
        pdict[name] = Person(name, 'male', ['Peter', 'Paul', 'Mary'])

assert count(pdict)['James'] == N
print(count(pdict)['James'])
Related