Python中的购物清单

Python中的购物清单,python,Python,我通过制作小程序来学习Python(以及一般的编程)。下面是一个基本的购物程序,它将根据所选食物返回要购买的物品列表 我想改进它,允许用户一次选择几种食物(例如,用户输入将是“1,2,3”),并返回一个基于该列表的配料列表 我应该采取什么样的方法?我使用的是Python 2.7,下面是我现有的代码: mm_soup = ['minced meat', 'potatoes', 'frozen vegetable'] sunday_soup = ['chicken with bones', 'noo

我通过制作小程序来学习Python(以及一般的编程)。下面是一个基本的购物程序,它将根据所选食物返回要购买的物品列表

我想改进它,允许用户一次选择几种食物(例如,用户输入将是“1,2,3”),并返回一个基于该列表的配料列表

我应该采取什么样的方法?我使用的是Python 2.7,下面是我现有的代码:

mm_soup = ['minced meat', 'potatoes', 'frozen vegetable']
sunday_soup = ['chicken with bones', 'noodles', 'soup vegetable']
gulas = ['pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas']

print "What would you like to cook on weekend?"
print "Here are the options:"
print "1. Minced Meat Soup"
print "2. Sunday Soup"
print "3. Gulas"

choose = raw_input("> ")

if choose == '1':
    print "Buy", ", ".join(mm_soup) + "." 

elif choose == '2':
    print "Buy", ", ".join(sunday_soup) + "."

elif choose == '3':
    print "Buy", ", ".join(gulas) + "."

else:
    print "Hmmm. No such food on the list."

我想您可以拆分输入的字符串并遍历其元素:

choose = raw_input("> ")
for choice in choose.split(', '): #split by comma and space
    if choice == '1':
        print "Buy", ", ".join(mm_soup) + "." 
    elif choice == '2':
        print "Buy", ", ".join(sunday_soup) + "."    
    elif choice == '3':
        print "Buy", ", ".join(gulas) + "."
    else:
        print "Hmmm. No such food on the list."
或者类似的:

choose = raw_input("> ");
selected = choose.split(', ') #split by comma and space

suggestion = '';
if '1' in selected :
    suggestion += ", ".join(mm_soup)
if '2' in selected :
    suggestion += ", ".join(sunday_soup)
if '3' in selected :
    suggestion += ", ".join(gulas)

if len(suggestion) > 0:
    print "Buy " + suggestion + "."
else:
    print "Hmmm. No such food on the list."

代码中存在一些常见问题,因此让我们首先修复这些问题

您有多个要呈现给用户的项目,并且您正在对这些值进行硬编码。这会让你付出很大的努力,因为你必须重复很多次。看看你的选择线,它们基本上都是一样的。您还可以通过定义描述和代码中的数字链接来重复自己。让我们尝试用数据结构来简化这一点

在这里,我们列出了所有选项——一个元组列表,定义了给定食物的名称和项目集。我们在这里使用集合,因为我们不需要订购物品

options = [
    ("Minced Meat Soup", {'minced meat', 'potatoes', 'frozen vegetable'}),
    ("Sunday Soup", {'chicken with bones', 'noodles', 'soup vegetable'}),
    ("Gulas", {'pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas'}),
]
这为我们提供了一个良好的数据结构

然后,我们可以提出问题,而不是手动构造问题,我们可以使用循环从选项列表中构造问题:

print "What would you like to cook on weekend?"
print "Here are the options:"
for option, (name, values) in enumerate(options, 1):
    print str(option)+". "+name
请注意的使用,以便为我们提供选项的编号。因为您希望从1开始,Python通常从0开始计数,所以我们也将其传入

这为我们提供了输出,但我们现在可以轻松地添加更多项,而无需修改现有代码。我们像以前一样询问,然后我们可以从列表中简单地获得他们给我们的索引,而不是加载
if
/
elif
s。我们首先必须将字符串更改为一个数字,然后去掉一个(因为Python从0开始计数)。这给了我们:

_, values = options[int(choose)-1]
import itertools

options = [
    ("Minced Meat Soup", {'minced meat', 'potatoes', 'frozen vegetable'}),
    ("Sunday Soup", {'chicken with bones', 'noodles', 'soup vegetable'}),
    ("Gulas", {'pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas'}),
]

print "What would you like to cook on weekend?"
print "Here are the options:"
for option, (name, values) in enumerate(options, 1):
    print str(option)+". "+name

choose = raw_input("> ")

try:
    shopping_list = [options[int(choice.strip())-1][1] for choice in choose.split(",")]
    print "Buy " + ", ".join(itertools.chain.from_iterable(shopping_list)) + "."
except (IndexError, ValueError):
    print "Hmmm. No such food on the list."
(使用tuple解包忽略第一个值,因为它是我们不需要的名称)

现在唯一的问题是,如果用户键入超出范围的数字或一个单词,例如,会发生什么情况。您可以在转换为int并使用它之前检查它,但是简单地尝试它,并在失败时捕获抛出的异常,这是python的风格。例如:

try:
    _, values = options[int(choose)-1]
    print "Buy", ", ".join(values) + "."
except (IndexError, ValueError):
    print "Hmmm. No such food on the list."
这使整个程序变得更小,并且注意添加新项目是多么容易,只需将它们添加到列表中即可

那么我们如何处理多个项目呢?现在这也很简单了。我们可以接受用户的输入,在逗号上拆分,去掉值以删除任何空格,然后执行与之前相同的操作:

for choice in choose.split(","):
    choice = choice.strip()

    try:
        _, values = options[int(choice)-1]
        print "Buy", ", ".join(values) + "."
    except (IndexError, ValueError):
        print "Hmmm. No such food on the list."
这是可行的,可以打印出多个购买行,但这不是最优的,更好的办法是生成一个更大的购物清单,其中包含所有需要的物品

我们可以通过在循环时构建一组所有项,然后打印出该集合来构建此功能

shopping_list = []
for choice in choose.split(","):
    choice = choice.strip()
    try:
        _, values = options[int(choice)-1]
        shopping_list.append(values)
    except (IndexError, ValueError):
        print "Hmmm. No such food on the list."
然而,这有点低效和丑陋。Python有一些内置功能来构建列表-。我们可以这样做:

try:
    shopping_list = [options[int(choice.strip())-1][3] for choice in choose.split(",")]
except (IndexError, ValueError):
    print "Hmmm. No such food on the list."
现在我们需要打印出列表中的所有值。请记住,这是一个集合列表,因此,“
”,“.join()
不会完全按照我们的要求执行。我们有两个选择。我们可以先使用生成器表达式连接集合,然后连接连接的字符串:

print "Buy " + ", ".join(", ".join(values) for values in shopping_list) + "."
或者,我们可以使用返回平坦迭代器:

print "Buy " + ", ".join(itertools.chain.from_iterable(shopping_list)) + "."
这给了我们:

_, values = options[int(choose)-1]
import itertools

options = [
    ("Minced Meat Soup", {'minced meat', 'potatoes', 'frozen vegetable'}),
    ("Sunday Soup", {'chicken with bones', 'noodles', 'soup vegetable'}),
    ("Gulas", {'pork meat', 'food cream', 'potatoes', 'onion', 'frozen peas'}),
]

print "What would you like to cook on weekend?"
print "Here are the options:"
for option, (name, values) in enumerate(options, 1):
    print str(option)+". "+name

choose = raw_input("> ")

try:
    shopping_list = [options[int(choice.strip())-1][1] for choice in choose.split(",")]
    print "Buy " + ", ".join(itertools.chain.from_iterable(shopping_list)) + "."
except (IndexError, ValueError):
    print "Hmmm. No such food on the list."
这会产生如下结果:

What would you like to cook on weekend?
Here are the options:
1. Minced Meat Soup
2. Sunday Soup
3. Gulas
> 1, 2
Buy potatoes, frozen vegetable, minced meat, chicken with bones, noodles, soup vegetable.

这是简短的,易于扩展,功能良好。你还可以处理一些其他问题(你想如何处理同一个项目的多个问题?你可能想研究一下),但这是基本的想法。

我不确定什么是家庭作业问题,所以这不是家庭作业(Boud称之为家庭作业)。如果它被错误标记,请随意更改。太好了,非常感谢。两种解决方案都很好,我更喜欢第二种,因为输出更优雅。我还需要弄清楚如何用逗号分隔两组或两组以上的成分(第二种解决方案不会将它们分开)。但我会自己想办法的。我追求的是逻辑。哇,这是一个惊人的答案,我学到了很多。现在我需要再读几遍,学习所有的新概念。我认为你的答案非常有价值,因为你不仅提供了一个很好的解决方案,而且你还教我如何用程序员的心态来应对所有这些挑战。非常感谢。实际上,我刚刚发现脚本的最终版本产生了一个错误:“名称‘shopping_list’未定义”。我不明白为什么。@finspin啊,是的,如果您提供的输入不在列表中,就会发生这种情况,我会编辑以修复。编辑:已编辑。问题是,购物清单的定义在try块中,但打印不在try块中,因此,如果打印失败,它将在尝试使用不存在的变量时抛出错误。此外,我认为在try块中,它应该读取选项[int(choice.strip())-1][1],而不是选项[int(choice.strip())-1][5]@finspin:我真的不知道那是怎么进去的,修好了。