Print available and show missing items from two dictionaries - python

I have a dictionary containing my available food in my fridge and I want to print the recipes I can make but also the ones that I could make if I had enough items (showing the number of items missing) and also print the ones that have an ingredient missing and thus what ingredient it is.
I just managed to show them all.
fridge = {
"orange" : 5,
"citron" : 3,
"sel" : 100,
"sucre" : 50,
"farine" : 250,
"tomates" : 6,
"huile" : 100,
"pomme" : 1,
"lait" : 1,
"pois chiche" : 1,
}
recipes = {
"jus_de_fruit" : {
"orange" : 3,
"citron" : 1,
"pomme" : 2
},
"salad" : {
"tomates" : 4,
"huile" : 10,
"sel" : 3
},
"crepes" : {
"lait" : 1,
"farine" : 250,
"oeufs" : 2
},
"glace" : {
"bac a glace" : 1,
"coulis abricot" : 1,
"batonnet" : 1
}
}
recette_dispo=[]
counter = 0
for recipe, recipe_contents in recipes.items():
if all(elem in list(fridge.keys()) for elem in list(recipes[recipe].keys())):
if all(recipe_contents[elem] <= fridge[elem] for elem in recipe_contents):
print(f'\n \n **** nice! you can make this recipe : {recipe} ****')
counter += 1
recette_dispo=recipe
else :
print(f'You have all ingredients but not enough in quantity for: {recipe}, you need: {list(recipe_contents.items())}')
else :
print(f'\n\n Tu nas pas tous les ingrédients pour : {recipe}')
print(f' You need these ingredients in order to make it : {list(recipe_contents.items())}')
print("\n I can make in total", counter, "recipe(s) from the ingredients in my fridge:",recette_dispo)
Output:
You have all ingredients but not enough in quantity for: jus_de_fruit, you need:[('orange', 3), ('citron', 1), ('pomme', 2)]
#here I would like instead only the missing numbers of ingredients
**** nice! you can make this recipe : salad ****
You don't have all ingredients for: crepes
You need these ingredients : [('lait', 1), ('farine', 250), ('oeufs', 2)]
#here I would like instead not all the ingredients of the recipe but only the ones missing in my fridge
Tu nas pas tous les ingrédients pour : glace
You need these ingredients: [('bac a glace', 1), ('coulis abricot', 1), ('batonnet', 1)]
I can make in total 1recipe(s) from the ingredients in my fridge: salade

You can use this example how to find missing items from the fridge:
fridge = {
"orange": 5,
"citron": 3,
"sel": 100,
"sucre": 50,
"farine": 250,
"tomates": 6,
"huile": 100,
"pomme": 1,
"lait": 1,
"pois chiche": 1,
}
recipes = {
"jus_de_fruit": {"orange": 3, "citron": 1, "pomme": 2},
"salad": {"tomates": 4, "huile": 10, "sel": 3},
"crepes": {"lait": 1, "farine": 250, "oeufs": 2},
"glace": {"bac a glace": 1, "coulis abricot": 1, "batonnet": 1},
}
for recipe_name, ingredients in recipes.items():
print(f"Recipe: {recipe_name}")
if (missing := ingredients.keys() - fridge.keys()) :
print("Missing ingredients:", missing)
else:
common = {
k: fridge[k] - ingredients[k]
for k in ingredients.keys() & fridge.keys()
}
if all(v >= 0 for v in common.values()):
print("All ingredients are OK")
else:
for i, v in common.items():
if v < 0:
print(f"Ingredient {i}: missing {-v} items")
print("-" * 80)
Prints:
Recipe: jus_de_fruit
Ingredient pomme: missing 1 items
--------------------------------------------------------------------------------
Recipe: salad
All ingredients are OK
--------------------------------------------------------------------------------
Recipe: crepes
Missing ingredients: {'oeufs'}
--------------------------------------------------------------------------------
Recipe: glace
Missing ingredients: {'batonnet', 'coulis abricot', 'bac a glace'}
--------------------------------------------------------------------------------

I tried to implement something similar to this years ago (in assembly language), but being a purchasing agent (in a previous life) did not provide me with the level of diligence required to update the inventory of my refrigerator, spice rack, etc. as I was using my ingredients. Things like ketchup, salad dressings, olives, and sliced pickles do not lend themselves well to bean-counting. Inventory management should be for pantries and deep freezers and should be avoided at the refrigerator level.
That's just my opinion, but if we take that into consideration and rely more upon the human touch we can make the primary mechanics of the program more elegant by using sets:
frigo = {
"orange" : 5,
"citron" : 3,
"sel" : 100,
"sucre" : 50,
"farine" : 250,
"tomates" : 6,
"huile" : 100,
"pomme" : 1,
"lait" : 1,
"pois chiche" : 1,
}
recettes = {
"jus_de_fruit" : {
"orange" : 3,
"citron" : 1,
"pomme" : 2
},
"salad" : {
"tomates" : 4,
"huile" : 10,
"sel" : 3
},
"crepes" : {
"lait" : 1,
"farine" : 250,
"oeufs" : 2
},
"glace" : {
"bac a glace" : 1,
"coulis abricot" : 1,
"batonnet" : 1
}
}
frigoSet = set(frigo)
peutFaire = []
nePeutPasFaire = dict()
for recette in recettes:
recetteSet = set(recettes[recette])
recetteSet.difference_update(frigoSet)
if len(recetteSet) == 0:
peutFaire.append(recette)
else:
nePeutPasFaire.update({recette: list(recetteSet)})
print("Vous avez les ingrédients pour faire:")
for i in peutFaire:
print(" {}".format(i))
print("\nIl manque des ingrédients pour les recettes suivantes:")
for i in nePeutPasFaire:
print(" {}".format(i))
for j in nePeutPasFaire[i]:
print(" {}".format(j))
The output of the program is:
Vous avez les ingrédients pour faire:
jus_de_fruit
salad
Il manque des ingrédients pour les recettes suivantes:
crepes
oeufs
glace
coulis abricot
bac a glace
batonnet
You can then use your personal knowledge of what you have in your refrigerator to determine what you want to make. After all, you may decide not to make those crepes this morning because you want to save the few eggs you have for brouillés tomorrow instead.
That's just to give you an idea of how you can use sets to get the basic information without looping through a bunch of comparisons for every ingredient in every recipe from the outset.

Related

solve function of pulp library in python : Type Error: must be real number, not str

Implementing Transportation problem in python
https://colab.research.google.com/drive/1ZMW3k-kk_0Zn6esTLPi5D9gyxWoAD4to?usp=sharing
from pulp import *
destination = ["D1" , "D2" , "D3"]
origin = ["O1", "O2","O3" ,"O4"]
supply = {
"O1" : 5,
"O2" : 8,
"O3" : 7,
"O4" : 14
}
demand = {
"D1" : 7,
"D2" : 9,
"D3" : 18
}
cost = {
"O1" :{"D1" : 2 , "D2" : 7 , "D3" : 4},
"O2" :{"D1" : 3 , "D2" : 3 , "D3" : 1},
"O3" :{"D1" : 5 , "D2" : 4 , "D3" : 7},
"O4" :{"D1" : 1 , "D2" : 6 , "D3" : 2}
}
prob = LpProblem("Transportation" , LpMinimize)
routes = [(i , j) for i in origin for j in destination]
route_variables = LpVariable.dicts("Route" , (origin , destination) , LpInteger)
# add the objective function in prob variable
prob += lpSum([route_variables[o][d]*cost[o][d] for (o,d) in routes])
# add the constraints in prob variable
# supply constraints
for o in origin:
prob += lpSum([route_variables[o][d] for d in destination]) <= supply[o]
# demand constraints
for d in destination:
prob += lpSum([route_variables[o][d] for o in origin]) >= demand[d]
prob.solve()
Whenever I run my code, this is the error I get and I don’t understand why.
Just replace the line:
route_variables = LpVariable.dicts("Route" , (origin , destination) , LpInteger)
To:
route_variables = LpVariable.dicts("Route" , (origin , destination) , cat=LpInteger)
This is because LpVariable.dicts looks like:
def dicts(self, name, indexs, lowBound = None, upBound = None, cat = LpContinuous, indexStart = []):
In order for the problem to be solved first the problem has to be written into an lp file. Use the statement
prob.writeLP("NameofFile.lp")
before calculating using prob.solve()

Sorting multi-dictionary in python

I have a datastructure like this:
poll = {
'LINK' : {'MoonRaccoon' : 1, 'TheDirtyTree' : 1},
'ZRX' : {'MoonRaccoon' : 1, 'Dontcallmeskaface' : 1, 'TheDirtyTree' : 1},
'XRP' : {'Dontcallmeskaface' : 1},
'XLM' : {'aeon' : 1, 'Bob' : 1}
}
I want it to ultimately print like this ordered by the number of who have requested each, then ticker symbol alphabetically, then the users also alphabetically
!pollresults
ZRX : Dontcallmeskaface, MoonRaccoon, TheDirtyTree
LINK : MoonRaccoon, TheDirtyTree
XLM : aeon, Bob
XRP: Dontcallmeskaface
Anyone really good at sorting that could help me do this.. I'm really new to python and super rusty at coding in general.
Thanks for any help.
Dictionaries can't really be sorted, but for the purposes of printing, this can be done.
poll = {
'LINK' : {'MoonRaccoon' : 1, 'TheDirtyTree' : 1},
'ZRX' : {'MoonRaccoon' : 1, 'Dontcallmeskaface' : 1, 'TheDirtyTree' : 1},
'XRP' : {'Dontcallmeskaface' : 1},
'XLM' : {'aeon' : 1, 'Bob' : 1}
}
def print_polls(poll):
for ticker in sorted(poll, key=lambda t: sum(poll[t].values()), reverse=True):
print(f"{ticker}: {', '.join(sorted(poll[ticker]))}")
This will give you the output you're looking for
Here you get a oneliner:
print (sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True))
Output:
[('ZRX', {'MoonRaccoon': 1, 'Dontcallmeskaface': 1, 'TheDirtyTree': 1}), ('LINK', {'MoonRaccoon': 1, 'TheDirtyTree': 1}), ('XLM', {'aeon': 1, 'Bob': 1}), ('XRP', {'Dontcallmeskaface': 1})]
To pretty print:
lst = sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True)
for elem in lst:
print (elem[0],":"," ".join(elem[1].keys()))
And because I really like oneliners, everything in one line!
print ("\n".join([" : ".join([elem[0]," ".join(list(elem[1].keys()))]) for elem in sorted(poll.items(), key = lambda item : len(list(item[1].keys())), reverse = True)]))
Output:
ZRX : MoonRaccoon Dontcallmeskaface TheDirtyTree
LINK : MoonRaccoon TheDirtyTree
XLM : aeon Bob
XRP : Dontcallmeskaface
count the votes in poll, get d
sort d decreasingly
get poll result in the order of step 2, and handle sorting the name lists
d = [[k, len(v)] for k, v in poll.items()]
d.sort(key=lambda name_vote: (-name_vote[-1],name_vote[0]))
pollresults = [name + ' : ' + ', '.join(sorted(poll[name].keys(), key=str.lower)) for name,vote in d]
result:
>>> pollresults
['ZRX : Dontcallmeskaface, MoonRaccoon, TheDirtyTree', 'LINK : MoonRaccoon, TheDirtyTree', 'XLM : aeon, Bob', 'XRP : Dontcallmeskaface']

Can not use .json information

Just a heads up I'm completely new to the coding scene and I'm having some issues using a json file
I've got the json to open using
json_queue = json.load(open('customer.json'))
but I just cant find the right code that allows me to make use of the info on the json. I think its because the json is an array not an object (probably completely wrong) My json currently looks like this
[
["James", "VW"],
["Katherine", "BMW"],
["Deborah", "renault"],
["Marguerite", "ford"],
["Kenneth", "VW"],
["Ronald", "Mercedes"],
["Donald", "BMW"],
["Al", "vauxhall"],
["Max", "porsche"],
["Carlos", "BMW"],
["Barry", "ford"],
["Donald", "renault"]
]
What I'm trying to do is take the persons name and the car type they are looking for and compare it too another json file that has the stock of cars in a shop but I'm currently stuck as to how I get python to actually use the information in that json.
I think I might of over explained my problem. My issue is that I am just starting a project using .json files and I can get python to open the file, but then I am unsure of how to get python to read that "James" wants a "VW" and then to go check the stock json to check if it is in stock. The stock json looks like this.
{
"VW": 4,
"BMW": 2,
"renault": 0,
"ford": 1,
"mercedes": 2,
"vauxhall": 1,
"porsche": 0,
}
What you have after the json.load() call is a plain python list of lists:
whishlist = [
["James", "VW"],
["Katherine", "BMW"],
["Deborah", "renault"],
["Marguerite", "ford"],
["Kenneth", "VW"],
["Ronald", "Mercedes"],
["Donald", "BMW"],
["Al", "vauxhall"],
["Max", "porsche"],
["Carlos", "BMW"],
["Barry", "ford"],
["Donald", "renault"]
]
where each sublist is a , pair. You can iterate over this list:
for name, car in whishlist:
print("name : {} - car : {}".format(name, car))
Now with your "other json file", what you have is a dict:
stock = {
"VW": 4,
"BMW": 2,
"renault": 0,
"ford": 1,
"mercedes": 2,
"vauxhall": 1,
"porsche": 0,
}
so all you have to do is to iterate over the whishlist list, check whether the car is in stock and print (or do anything else) the result:
for name, car in whishlist:
in_stock = stock.get(car, 0)
print("for {} : car {} in stock : {}".format(name, car, in_stock))
for James : car VW in stock : 4
for Katherine : car BMW in stock : 2
for Deborah : car renault in stock : 0
for Marguerite : car ford in stock : 1
for Kenneth : car VW in stock : 4
for Ronald : car Mercedes in stock : 0
for Donald : car BMW in stock : 2
for Al : car vauxhall in stock : 1
for Max : car porsche in stock : 0
for Carlos : car BMW in stock : 2
for Barry : car ford in stock : 1
for Donald : car renault in stock : 0

How could I print connected parts from a dictionary?

How could I print which rooms are connected to the "de Lobby"? The things I tried returned string erros or other errors.
kamers = {
1 : { "naam" : "de Lobby" ,
"trap" : 2,
"gangrechtdoor" : 3 } ,
2 : { "naam" : "de Trap" ,
"lobby" : 1,
"note" : "Terwijl je de trap oploopt hoor je in de verte Henk van Ommen schreeuwen" } ,
3 : { "naam" : "de Gang rechtdoor" ,
"lobby" : 1,
"gymzaal" : 4,
"concergie" : 5,
"gangaula" : 6 } ,
This prints where you are, but as you can see, not which rooms are connected.
print("Hier ben je: " + kamers[currentKamer]["naam"])
print("hier kan je naartoe: ")
Does this do what you want?
kamers = {
1: {"naam": "de Lobby",
"trap": 2,
"gangrechtdoor": 3},
2: {"naam": "de Trap",
"lobby": 1,
"note": "Terwijl je de trap oploopt hoor je in de verte Henk van Ommen schreeuwen"},
3: {"naam": "de Gang rechtdoor",
"lobby": 1,
"gymzaal": 4,
"concergie": 5,
"gangaula": 6}}
def find_connected_rooms(room_name, rooms):
room_number = next(room_number for room_number, props in rooms.items() if props['naam'] == room_name)
for room_props in rooms.values():
if room_number in room_props.values():
yield room_props['naam']
if __name__ == '__main__':
for connected_room in find_connected_rooms('de Lobby', kamers):
print(connected_room)
Output
de Trap
de Gang rechtdoor
Question is not quite clear but I assume you are looking for the items which has lobby key or any key with 1 as value
kamers[1] is lobby and it is "naam" is "de Lobby".
so This gets by if items inside has value 1 (Lobby's key)
[i for i in kamers.values() if 1 in i.values()]
or you can check if the key 'lobby' exists
[i for i in kamers.values() if i.get('lobby',None) ]
to get the name of the rooms you can replace for "i" with i['naam']
[i['naam'] for i in kamers.values() if i.get('lobby',None) ]
which returns
['de Trap', 'de Gang rechtdoor']

Impossible to pass a variable in key return in MongoDB or NoSQL DB?

Here's my code:
dob = 1
email = 1
nationality = 1
work = 1
situation = 1
skype = 1
user_id = ObjectId(self.get_argument("id"))
contact_id = ObjectId(self.get_argument("contactId"))
contact_confidentiality = db.cara.users.find_one({"_id" : contact_id}, {"profil.private.confidential" : 1})
confidentiality = []
for i in contact_confidentiality["profil"]["private"]["confidential"]:
if i == "dob":
dob = 0
elif i == "email":
email = 0
elif i == "nationality":
nationality = 0
elif i == "work":
work = 0
elif i == "situation":
situation = 0
elif i == "skype":
skype = 0
elif i == "facebook":
facebook = 0
contact = db.cara.users.find_one({"_id" : contact_id}, {"profil.private.first_name": 1, "profil.private.last_name": 1, "profil.gender": 1, "profil.dob": dob, "profil.nationality": nationality, "profil.work": work, "profil.private.email_address": email, "profil.private.situation": situation, "profil.private.skype": skype})
MongoDB doesn't want to pass in the last line of my code: dob, nationality, work, email. How can I pass variable?
EDIT:
contact_confidentiality = db.cara.users.find_one({"_id" : contact_id}, {"profil.private.confidential" : 1})
projection = {
'profil.private.first_name' :1 ,
'profil.private.last_name' : 1,
'profil.gender' : 1,
'profil.dob' : 1,
'profil.private.email_address' : 1,
'profil.nationality' : 1,
'profil.work' : 1,
'profil.private.situation' : 1,
'profil.private.skype' : 1,
'profil.facebook' : 1
}
for i in contact_confidentiality["profil"]["private"]["confidential"]:
i_json = self._doc_to_json(i)
logging.info(i_json)
del projection[i_json] # I need a key like "profil.nationality" but my key is "nationality"
contact = db.cara.users.find_one({"_id" : contact_id}, projection)
Currently, there is a limitation that you can only include or exclude, but not both in a projection. So if you are going to pass a projection, they need to either be all 1's or all 0's.
There is one exception to this which is when you are using covered indexes, you can exclude the _id field, and include other fields.
There is currently a ticket requesting that you be able to mix include and exclude, but it is not implemented yet. Check out http://jira.mongodb.org/browse/SERVER-391
To solve the specific problem in the query above, I suggest you take a different approach to your query... Instead of creating a projection by setting 1's and 0's, you can simply build a projection that only includes the things you want and leaves out the others. For example, something like this:
user_id = ObjectId(self.get_argument("id"))
contact_id = ObjectId(self.get_argument("contactId"))
contact_confidentiality = db.cara.users.find_one({"_id" : contact_id}, {"profil.private.confidential" : 1})
projection = {
'profil' : {
'private' : {
'first_name': 1,
'last_name':1,
'gender':1,
'dob' : 1,
'email' : 1,
'nationality': 1,
'work' : 1,
'situation' : 1,
'skype' : 1,
'facebook' : 1
}
}
}
for i in contact_confidentiality["profil"]["private"]["confidential"]:
projection['profil']['private'].remove(i)
contact = db.cara.users.find_one({"_id" : contact_id}, projection)

Categories

Resources