I have next code and I create objects for every entry pet:
from itertools import groupby
class Petshop():
def __init__(self, entryDate, name, ownerName):
self.entryDate = entryDate
self.name = name
self.ownerName = ownerName
class Pets():
def __init__(self):
self.petsList = []
def addPets(self, entryDate, name, ownerName):
entry_pet = Petshop(entryDate, name, ownerName)
self.petsList.append(entry_pet)
def printPets(self):
self.petsList.sort(key=lambda p: p.entryDate)
counter = 0
for group in groupby(self.petsList, key=lambda p: p.entryDate):
ls = list(group)
print("---------------", ls[0], '------------------')
for pet in list(ls[1]):
print("Name:", pet.name)
print("Owner name:", pet.ownerName)
if pet.name in list(ls[1]):
counter += 1
print('There are ',counter,'pets with the same name')
pet = Pets()
pet.addPets('04/13/2021','Pinky', 'David Smith')
pet.addPets('07/10/2020', 'Charlie', 'Joe Davis')
pet.addPets('04/13/2021','Pinky', 'Daniel Trincot')
pet.addPets('07/10/2020', 'Kenny', 'Susan Jones')
pet.addPets('12/22/2018', 'Teddy', 'Carl Johnson')
pet.addPets('07/10/2020', 'Kenny', 'Richard Campbell')
pet.addPets('04/13/2021','Max', 'Bryan Miller')
pet.addPets('07/10/2020', 'Buddy', 'Kathy Brown')
pet.addPets('07/10/2020', 'Kenny', 'John Brown')
pet.printPets()
With that code I would like to count how many repeated pets entry by date, so for example I expect in console:
--------------- 04/13/2021 ------------------
Name: Pinky
Owner name: David Smith
Name: Pinky
Owner name: Daniel Trincot
Name: Max
Owner name: Bryan Miller
There are 2 pets with the same name
--------------- 07/10/2020 ------------------
Name: Charlie
Owner name: Joe Davis
Name: Kenny
Owner name: Susan Jones
Name: Kenny
Owner name: Richard Campbell
Name: Buddy
Owner name: Kathy Brown
Name: Kenny
Owner name: John Brown
There are 3 pets with the same name
--------------- 12/22/2018 ------------------
Name: Teddy
Owner name: Carl Johnson
There are 0 pets with the same name
I tried to do that with:
if pet.name in list(ls[1]):
counter += 1
But that does not work, because I think my code does not get into the if and I just get in console:
--------------- 04/13/2021 ------------------
Name: Pinky
Owner name: David Smith
There are 0 pets with the same name
Name: Pinky
Owner name: Daniel Trincot
There are 0 pets with the same name
Name: Max
Owner name: Bryan Miller
There are 0 pets with the same name
--------------- 07/10/2020 ------------------
Name: Charlie
Owner name: Joe Davis
There are 0 pets with the same name
Name: Kenny
Owner name: Susan Jones
There are 0 pets with the same name
Name: Kenny
Owner name: Richard Campbell
There are 0 pets with the same name
Name: Buddy
Owner name: Kathy Brown
There are 0 pets with the same name
Name: Kenny
Owner name: John Brown
There are 0 pets with the same name
--------------- 12/22/2018 ------------------
Name: Teddy
Owner name: Carl Johnson
There are 0 pets with the same name
So I come here for help.
Changes to printPets
method (adjusted for PEP 8 but still should be clear what each name refers to) (more detailed explanation in the complete code example below):
from collections import Counter
...
def print_all_pets(self):
for date, group in groupby(sorted(self.pets_list, key=lambda x: x.entry_date),
key=lambda x: x.entry_date):
print(f'{"-" * 20} {date} {"-" * 20}')
counter = Counter()
for pet in group:
print(f"Name: {pet.name}")
print(f"Owner name: {pet.owner_name}")
counter[pet.name] += 1
print(f'There are {max(counter.values())} '
f'pets with the same name')
Complete code example (it also follows PEP 8 which I suggest you follow too); most of the explanation is in the code comments:
from itertools import groupby
from dataclasses import dataclass, field
from collections import Counter
# using dataclasses because they make it easier
# to create more data driven objects and they can pre-build
# all the comparison methods so that sorting is way easier
# and you can exclude what not to sort
@dataclass(order=True)
class PetShop:
entry_date: str
name: field(default_factory=str, compare=False)
owner_name: field(default_factory=str, compare=False)
class Pets:
def __init__(self):
self.pets_list = []
def add_pet(self, entry_date, name, owner_name):
entry_pet = PetShop(entry_date, name, owner_name)
self.pets_list.append(entry_pet)
def print_all_pets(self):
# as you can see no key is needed for sorting the `PetShop` instances
# because dataclass allows to do so, then just group them by their date
# which seems to require some function, also unpack both values:
# the date and the group
for date, group in groupby(sorted(self.pets_list), key=lambda x: x.entry_date):
# use f-string for formatting and also you can multiply strings
print(f'{"-" * 20} {date} {"-" * 20}')
# use counter for counting and update it with the pet name
# each iteration
counter = Counter()
for pet in group:
print(f"Name: {pet.name}")
print(f"Owner name: {pet.owner_name}")
# update the counter
counter[pet.name] += 1
# then get the highest count
print(f'There are {max(counter.values())} '
f'pets with the same name')
pets = Pets()
# use a list to make the code less repetitive, this
# allows to loop over the list and add each item to the
# pets.pets_list less repetitively than calling the `add_pet`
# method multiple times manually
pet_shops = [
('04/13/2021', 'Pinky', 'David Smith'),
('07/10/2020', 'Charlie', 'Joe Davis'),
('04/13/2021', 'Pinky', 'Daniel Trincot'),
('07/10/2020', 'Kenny', 'Susan Jones'),
('12/22/2018', 'Teddy', 'Carl Johnson'),
('07/10/2020', 'Kenny', 'Richard Campbell'),
('04/13/2021', 'Max', 'Bryan Miller'),
('07/10/2020', 'Buddy', 'Kathy Brown'),
('07/10/2020', 'Kenny', 'John Brown')
]
for e_date, p_name, o_name in pet_shops:
pets.add_pet(e_date, p_name, o_name)
pets.print_all_pets()
And your original issue was that you checked whether a string was in a list of PetShop
instances so it would always evaluate to False
(and the condition even if properly used (actually check if the pet name is in the list of pet names for example), it would just give the count of total pets per groupoing). So for counting as shown above I would suggest using collections.Counter
since it is way easier than to manually make the algorithm for that.
Useful sources:
dataclasses
library (built-in)collections.Counter
docs (built-in)itertools.groupby
docs (more for the example)On PEP 8:
I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case
, class names in CapitalCase
. Don't have space around =
if it is used as a part of keyword argument (func(arg='value')
) but have space around =
if it is used for assigning a value (variable = 'some value'
). Have space around operators (+-/
etc.: value = x + y
(except here value += x + y
)). Have two blank lines around function and class declarations. Class methods have one blank line around them.