遍历命名元组列表,选择餐厅
Iterating over list of namedtuples, selecting restaurants
我的功能是 returns 价格等于或低于指定值的餐厅。这是我当前的代码:
Restaurant = namedtuple('Restaurant', 'name cuisine phone menu')
Dish = namedtuple('Dish', 'name price calories')
r1 = Restaurant('Thai Dishes', 'Thai', '334-4433', [Dish('Mee Krob', 12.50, 500),
Dish('Larb Gai', 11.00, 450)])
r2 = Restaurant('Taillevent', 'French', '01-44-95-15-01',
[Dish('Homard Bleu', 45.00, 750),
Dish('Tournedos Rossini', 65.00, 950),
Dish("Selle d'Agneau", 60.00, 850)])
collection =[r1,r2]
def Collection_is_cheap(C, price):
result = []
if not C:
return ''
else:
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.append(rest)
return result
但是当我尝试 运行 时:
print(Collection_is_cheap(collection, 28))
我得到的是一长串正确的餐厅,但重复了。
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)])]
而对于正确的输出,它应该只打印一次这两家餐厅。我该如何更正这个问题,以便函数仅 returns:
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]
只要有匹配项就停止循环查看餐厅菜单;为此使用 break
:
def Collection_is_cheap(C, price):
result = []
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.append(rest)
break # stop the rest.menu loop, go to the next
return result
请注意,我删除了 if not C: return ''
部分;最好不要 return 来自一个函数的不同类型的对象。
演示:
>>> def Collection_is_cheap(C, price):
... result = []
... for rest in C:
... for dish in rest.menu:
... if dish.price <= price:
... result.append(rest)
... break # stop the rest.menu loop, go to the next
... return result
...
>>> print(Collection_is_cheap(collection, 28))
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=(Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450))), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=(Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)))]
另一种方法是使用 set 而不是列表;集合只能容纳 个唯一对象,因此多次添加餐厅不会有任何效果:
def Collection_is_cheap(C, price):
result = set()
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.add(rest)
return list(result)
为此,您还需要使菜单使用元组,而不是列表:
r1 = Restaurant('Thai Dishes', 'Thai', '334-4433', (
Dish('Mee Krob', 12.50, 500),
Dish('Larb Gai', 11.00, 450)))
r2 = Restaurant('Taillevent', 'French', '01-44-95-15-01', (
Dish('Homard Bleu', 45.00, 750),
Dish('Tournedos Rossini', 65.00, 950),
Dish("Selle d'Agneau", 60.00, 850)))
r3 = Restaurant('Pascal', 'French', '940-752-0107', (
Dish('Escargots', 12.95, 250),
Dish('Poached salmon', 18.50, 550),
Dish("Rack of lamb", 24.00, 850),
Dish("Marjolaine cake", 8.50, 950)))
使它们完全免疫table,这是使用集合的要求。
使用 set
仅收集唯一餐厅的另一个影响是,餐厅的顺序 return 可能会改变,因为集合是无序的。相反,它们以依赖于实现的顺序保存对象,这有利于有效地测试已经存在的对象。
演示;对于这个只有两家廉价餐厅的简单示例,恰好 与第一个版本 return 编辑的订单相匹配:
>>> def Collection_is_cheap(C, price):
... result = set()
... for rest in C:
... for dish in rest.menu:
... if dish.price <= price:
... result.add(rest)
... return list(result)
...
>>> print(Collection_is_cheap(collection, 28))
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=(Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450))), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=(Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)))]
如果您不能将元组用于菜单序列,并且由于某种原因不能使用 break
技巧,则您每次都必须使用(缓慢且昂贵的)列表成员测试:
def Collection_is_cheap(C, price):
result = []
for rest in C:
for dish in rest.menu:
if dish.price <= price and rest not in result:
result.append(rest)
return result
这是缓慢且昂贵的,因为 Python 将分别测试列表中的每个元素以查看 rest == element
是否为真,而对于集合,一个称为 散列的技巧 table 用于快速检查对象是否已经存在,通常只需要一次计算检查。
我的功能是 returns 价格等于或低于指定值的餐厅。这是我当前的代码:
Restaurant = namedtuple('Restaurant', 'name cuisine phone menu')
Dish = namedtuple('Dish', 'name price calories')
r1 = Restaurant('Thai Dishes', 'Thai', '334-4433', [Dish('Mee Krob', 12.50, 500),
Dish('Larb Gai', 11.00, 450)])
r2 = Restaurant('Taillevent', 'French', '01-44-95-15-01',
[Dish('Homard Bleu', 45.00, 750),
Dish('Tournedos Rossini', 65.00, 950),
Dish("Selle d'Agneau", 60.00, 850)])
collection =[r1,r2]
def Collection_is_cheap(C, price):
result = []
if not C:
return ''
else:
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.append(rest)
return result
但是当我尝试 运行 时:
print(Collection_is_cheap(collection, 28))
我得到的是一长串正确的餐厅,但重复了。
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)])]
而对于正确的输出,它应该只打印一次这两家餐厅。我该如何更正这个问题,以便函数仅 returns:
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=[Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450)]), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=[Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)]
只要有匹配项就停止循环查看餐厅菜单;为此使用 break
:
def Collection_is_cheap(C, price):
result = []
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.append(rest)
break # stop the rest.menu loop, go to the next
return result
请注意,我删除了 if not C: return ''
部分;最好不要 return 来自一个函数的不同类型的对象。
演示:
>>> def Collection_is_cheap(C, price):
... result = []
... for rest in C:
... for dish in rest.menu:
... if dish.price <= price:
... result.append(rest)
... break # stop the rest.menu loop, go to the next
... return result
...
>>> print(Collection_is_cheap(collection, 28))
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=(Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450))), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=(Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)))]
另一种方法是使用 set 而不是列表;集合只能容纳 个唯一对象,因此多次添加餐厅不会有任何效果:
def Collection_is_cheap(C, price):
result = set()
for rest in C:
for dish in rest.menu:
if dish.price <= price:
result.add(rest)
return list(result)
为此,您还需要使菜单使用元组,而不是列表:
r1 = Restaurant('Thai Dishes', 'Thai', '334-4433', (
Dish('Mee Krob', 12.50, 500),
Dish('Larb Gai', 11.00, 450)))
r2 = Restaurant('Taillevent', 'French', '01-44-95-15-01', (
Dish('Homard Bleu', 45.00, 750),
Dish('Tournedos Rossini', 65.00, 950),
Dish("Selle d'Agneau", 60.00, 850)))
r3 = Restaurant('Pascal', 'French', '940-752-0107', (
Dish('Escargots', 12.95, 250),
Dish('Poached salmon', 18.50, 550),
Dish("Rack of lamb", 24.00, 850),
Dish("Marjolaine cake", 8.50, 950)))
使它们完全免疫table,这是使用集合的要求。
使用 set
仅收集唯一餐厅的另一个影响是,餐厅的顺序 return 可能会改变,因为集合是无序的。相反,它们以依赖于实现的顺序保存对象,这有利于有效地测试已经存在的对象。
演示;对于这个只有两家廉价餐厅的简单示例,恰好 与第一个版本 return 编辑的订单相匹配:
>>> def Collection_is_cheap(C, price):
... result = set()
... for rest in C:
... for dish in rest.menu:
... if dish.price <= price:
... result.add(rest)
... return list(result)
...
>>> print(Collection_is_cheap(collection, 28))
[Restaurant(name='Thai Dishes', cuisine='Thai', phone='334-4433', menu=(Dish(name='Mee Krob', price=12.5, calories=500), Dish(name='Larb Gai', price=11.0, calories=450))), Restaurant(name='Pascal', cuisine='French', phone='940-752-0107', menu=(Dish(name='Escargots', price=12.95, calories=250), Dish(name='Poached salmon', price=18.5, calories=550), Dish(name='Rack of lamb', price=24.0, calories=850), Dish(name='Marjolaine cake', price=8.5, calories=950)))]
如果您不能将元组用于菜单序列,并且由于某种原因不能使用 break
技巧,则您每次都必须使用(缓慢且昂贵的)列表成员测试:
def Collection_is_cheap(C, price):
result = []
for rest in C:
for dish in rest.menu:
if dish.price <= price and rest not in result:
result.append(rest)
return result
这是缓慢且昂贵的,因为 Python 将分别测试列表中的每个元素以查看 rest == element
是否为真,而对于集合,一个称为 散列的技巧 table 用于快速检查对象是否已经存在,通常只需要一次计算检查。