Как я могу перебрать список по двум различным критериям? - PullRequest
0 голосов
/ 18 июня 2019

Привет, ребята, у меня проблема с циклом for, из-за которого я не смог найти решение для онлайн.

Допустим, я создал два класса, один для людей и один для животных.Установив метод цикла для класса животных, который перебирает список возрастов людей, я хотел найти владельца для каждого питомца, который имеет такой же возраст или, по крайней мере, наименьший разрыв в возрасте (этот пример только для того, чтобы код выглядел проще).Я использовал функцию min(), чтобы найти человека с наименьшим возрастным разрывом, который работает нормально.

Но что, если я добавлю еще один критерий в процесс выбора?Например, я хотел бы назначить животное только тем людям, которые владеют менее чем 3 домашними животными, а это означает, что, хотя у человека наименьший разрыв в возрасте, домашнее животное не может быть назначено этому человеку, если у него уже есть 3 домашних животных.В этом случае цикл должен был бы найти следующего человека с наименьшим возрастным разрывом, которому принадлежит менее 3 домашних животных.В моем случае A1 нужно было бы назначить на P1, так как именно человек с наименьшим возрастным разрывом владеет менее чем 3 домашними животными.

Вот мой код:

class People:
    def __init__(self, name, age, pets_owned):
        self.name=name
        self.age=age
        self.pets_owned=pets_owned

P1=People("John",16, 1)
P2=People("Alex",10, 4)
P3=People("Anna", 20, 3)


People_List=[P1, P2, P3]
People_Age=[P1.age, P2.age, P3.age]

class Animal:
    def __init__(self, name, age, owner):
        self.name=name
        self.age=age
        self.owner=owner

    def find(self):
        closest_age = (min(People_Age, key=lambda x: abs(x - self.age)))
        for a in People_List:
            if a.age ==closest_age and a.pets_owned<3:
                self.owner=a.name
                a.pets_owned+=1
                break

            elif a.age==closest_age and a.pets_owned >=3:
                pass #this is where I`m stuck


        print(self.owner)


A1=Animal("Snoopy",7,"not_owned_yet")


A1.find()

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Если вы знаете, что не собираетесь включать определенных людей из-за критериев, я бы предварительно отфильтровал входящий список, чтобы исключить этих людей. По сути, вместо того, чтобы вообще использовать цикл for, просто отфильтруйте список, найдите min и добавьте питомца.

class People:
    def __init__(self, name, age, pets_owned):
        self.name=name
        self.age=age
        self.pets_owned=pets_owned

P1=People("John",16, 1)
P2=People("Alex",10, 4)
P3=People("Anna", 20, 3)


People_List=[P1, P2, P3]
People_Age=[P1.age, P2.age, P3.age]

class Animal:
    def __init__(self, name, age, owner):
        self.name=name
        self.age=age
        self.owner=owner

    def find(self):
        people_with_less_than_3 = filter(lambda x: x.pets_owned<3, People_List) # filter the list to only include people that have less than 3 pets
        try:
            person_with_closest_age = min(people_with_less_than_3, key=lambda x: abs(x.age - self.age)) # change this to return a person as well
        except:
            # do something if no person with < 3 pets
        self.owner = person_with_closest_age.name
        print(self.owner)


A1=Animal("Snoopy",7,"not_owned_yet")


A1.find()
0 голосов
/ 18 июня 2019

Вы можете сортировать по нескольким атрибутам, если ваш ключ сортировки возвращает кортеж. В моем примере сначала мы сортируем по разнице в возрасте (более высокий приоритет), а затем по количеству домашних животных (более низкий приоритет). Вам не нужно использовать sorted, как я, поскольку я использую его только для демонстрации работы сортировки на основе нескольких атрибутов. Вы можете использовать min с тем же ключом, чтобы получить наиболее подходящего человека. Вы также захотите изменить assign_new_owner, чтобы фактически назначать нового владельца (используя min), а не печатать людей:

class Person:

    def __init__(self, name, age, pets_owned):
        self.name = name
        self.age = age
        self.pets_owned = pets_owned

    def __str__(self):
        return f"{self.name}, age {self.age} owns {self.pets_owned} pet(s)."

class Animal:

    def __init__(self, name, age, owner=None):
        self.name = name
        self.age = age
        self.owner = owner

    def assign_new_owner(self, people):
        sorted_people = sorted(people, key=lambda p: (abs(p.age - self.age), p.pets_owned))
        for person in sorted_people:
            print(person)

def main():

    people = [
        Person("Alex", 16, 0),
        Person("Nigel", 15, 2),
        Person("Fred", 10, 3),
        Person("Tom", 10, 0),
        Person("Tyler", 15, 0),
        Person("Sam", 15, 1)
        ]

    animal = Animal("Snoopy", 10)
    animal.assign_new_owner(people)

    return 0

if __name__ == "__main__":
    import sys
    sys.exit(main())

Выход:

 Tom, age 10 owns 0 pet(s).
 Fred, age 10 owns 3 pet(s).
 Tyler, age 15 owns 0 pet(s).
 Sam, age 15 owns 1 pet(s).
 Nigel, age 15 owns 2 pet(s).
 Alex, age 16 owns 0 pet(s).

РЕДАКТИРОВАТЬ: после использования min код может выглядеть примерно так:

class Person:

    def __init__(self, name, age, pets_owned):
        self.name = name
        self.age = age
        self.pets_owned = pets_owned

    def __str__(self):
        return f"{self.name}, age {self.age} owns {self.pets_owned} pet(s)."

class Animal:

    def __init__(self, name, age, owner=None):
        self.name = name
        self.age = age
        self.owner = owner

    def __str__(self):
        return f"{self.name}, age {self.age} is owned by {self.owner.name if self.owner else 'no one'}."

    def assign_new_owner(self, people):
        self.owner = min(people, key=lambda p: (abs(p.age - self.age), p.pets_owned))

def main():

    people = [
        Person("Alex", 16, 0),
        Person("Nigel", 15, 2),
        Person("Fred", 10, 3),
        Person("Tom", 10, 0),
        Person("Tyler", 15, 0),
        Person("Sam", 15, 1)
        ]

    animal = Animal("Snoopy", 10)
    print(animal)
    animal.assign_new_owner(people)
    print(animal)

    return 0

if __name__ == "__main__":
    import sys
    sys.exit(main())

Выход:

Snoopy, age 10 is owned by no one.
Snoopy, age 10 is owned by Tom.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...