Вопрос

I'm trying to use Python to create a program that will allow a user to input the number of people a recipe needs to serve and recalculate the quantities of the original recipe based on its old serving number.

For example the final calculation would be something along the lines of:

(ingredient quantity / old serve number) * new serve number

The first piece of code is used to write both the people the recipe serves, the ingredients and ingredient details to a pickled file. Ingredient details are looped and stored in an array so that multiple ingredients can be stored.

 serve = int (input ("Enter number of people: ")) #Prompts user for number of people the recipe will serve

 recipedetails=[]#starts array

 for i in range (ing_number): *#Loops 3 intented inputs by ing_number amount of times*
        name = input ("Enter ingredient name: ") *#Ingredient name variable*
        amount = int (input ("Enter quantity of ingredient ")) *#Quantity variable*
        unit =  input ("Enter unit of ingredient: ") *#Unit variable*

        recipedetails.append ((name, amount, unit)) *#closes array with variables added*

        recipeinfo = serve , recipedetails *# adds serve and recipedetails to recipe info variable*

        recipe = open(rec_name+".dat", "wb") *#Creates .dat file with recipe name as file  name.*
        pickle.dump(recipeinfo, recipe) *#Adds this recipeinfo to .dat file*

This all works correctly and both the people the recipe serves and the ingredients are stored in the pickled file. But, the problem lies in the recalling of the information from the array. The variable amount needs to be recalled from the array to be multiplied by a new number of people.

 import os 
 textfiles = [f for f in os.listdir(os.curdir) if f.endswith (".dat") ] *#imports* 
 print (textfiles)
 rec_name = input ("Enter recipe name: ") *#Prompts user for recipe name.*
 rd = open (rec_name+ ".dat", "rb") *#Opens the file the user selected*
 recipeinfo = pickle.load(rd) *#Gives loaded file a variable so it can be displayed*

 print(recipeinfo) *# Prints recalled information*

The code up to this point works ok. Using this I can view the recipeinfo from the saved array. However, I have no idea how to split the array back up into the original variables.

  • name - ingredient name shown before amount
  • amount - needed to be divided by people and multiplied by new amount
  • unit - shown after amount
  • serve - original value needed to be divide amount by to get new value.

How do I go amount splitting this pickled file into these variables?

Это было полезно?

Решение

Your structure appears to be:

recipeinfo == (serve, [(name, amount, unit), (name, amount, unit), ...])

So you can turn recipeinfo back into these variables using:

serve, recipedetails = recipeinfo
for name, amount, unit in recipedetails:

However, if you only get the list recipedetails back from pickle.load you can just do:

for name, amount, unit in recipeinfo:

Другие советы

This issue doesn't really have to do with pickling specifically.

Consider:

def return_a_tuple(a, b, c):
    return (a, (b, c))

x = return_a_tuple(1, 2, 3)

How do you extract a, b, and c from x?

The answer, as jonrsharpe says, is to do something like:

(a, (b, c)) = x

Also, I suspect that instead of

recipedetails.append((name, amount, unit))
recipeinfo = serve , recipedetails

You meant something like

recipedetail = (name, amount, unit)
recipedetails.append(recipedetail)
recipeinfo = serve, repcipedetail

Your original code is creating pairs of serve with a list of every recipe detail you've seen so far, instead of only the one you've just read in.

Alternatively, you could consider using a namedtuple:

from collections import namedtuple

RecipeDetail = namedtuple('RecipeDetail', ['name', 'amount', 'unit'])
RecipeInfo = namedtuple('RecipeInfo', ['serve', 'recipe_detail'])

You can then do something like

recipedetail = RecipeDetail(name, amount, unit)
recipedetails.append(recipedetail)
recipeinfo = RecipeInfo(serve, recipedetail)

Now you can access sub-fields by doing:

recipedetail.name
recipeinfo.recipe_detail.amount

You want to pull out the list of tuples containing the name, amount and unit values.

import sys
ingredients_list = ''
for item in recipeinfo:
    if type(item) == list:
        ingredients_list = item
        continue

Verify that you found a list:

if ingredients_list == '':
    print("I never found a list!")
    sys.exit(1)

for name, amount, unit in ingredients_list:
     print("{0}: {1} {2}").format(name, amount, unit)
    . . .

And use these values to do your calculations, print instructions, etc.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top