如何迭代具有两个不同条件的列表?
How can I iterate over a list with two different criteria?
大家好,我遇到了一个 for 循环的问题,我在网上找不到解决方案。
假设我创建了两个 classes,一个用于人,一个用于动物。通过为动物 class 设置循环方法来遍历人民年龄列表,我想为每只具有相同年龄或至少最小年龄差距的宠物找到主人(这个例子只是为了制作代码看起来更简单)。我使用 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()
如果您知道由于某个标准您不会包括某些人,我会 pre-filter 传入列表以排除这些人。基本上,根本不使用 for 循环,只需过滤列表,然后找到最小值,然后添加宠物。
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()
您可以根据多个属性进行排序,方法是让您的排序键 return 成为一个元组。在我的示例中,首先我们根据年龄差距(较高优先级)排序,然后根据拥有的宠物数量(较低优先级)排序。您不需要像我一样使用 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.
大家好,我遇到了一个 for 循环的问题,我在网上找不到解决方案。
假设我创建了两个 classes,一个用于人,一个用于动物。通过为动物 class 设置循环方法来遍历人民年龄列表,我想为每只具有相同年龄或至少最小年龄差距的宠物找到主人(这个例子只是为了制作代码看起来更简单)。我使用 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()
如果您知道由于某个标准您不会包括某些人,我会 pre-filter 传入列表以排除这些人。基本上,根本不使用 for 循环,只需过滤列表,然后找到最小值,然后添加宠物。
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()
您可以根据多个属性进行排序,方法是让您的排序键 return 成为一个元组。在我的示例中,首先我们根据年龄差距(较高优先级)排序,然后根据拥有的宠物数量(较低优先级)排序。您不需要像我一样使用 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.