Python 3.4 list to do different tasks - python

I have this list:
list1 = [
'aapl':'apple',
'tgt':'target',
'nke':'nike',
'mcd':'Mc Donald',
'googl':'google',
'yhoo':'yahoo',
'rl':'Polo Ralph lauren'
]
I wish to execute this
q = 0
while q < len(list1):
code_to_be_executed
q = q+1
But only for the 1st part (aapl,tgt,nke,mdc,rl,yhoo,etc) and the the 2nd part (the company name as google, yahoo , polo ralph lauren, etc ) to be printed in something like this : nke = nike to the user
The problem is it will perform the q task to everything even for the company name which is not what I want) I know I could seperate the abreviations and the company name in two different list but how could I print it like the nke = Nike comp. ? thank you very much

What I believe you are trying to do is a basic printing of a key/value data structure (called a dict in Python):
Example:
data = {
'aapl': 'apple', 'tgt': 'target', 'nke': 'nike', 'mcd': 'Mc Donald',
'googl': 'google', 'yhoo': 'yahoo', 'rl': 'Polo Ralph lauren'
}
for k, v in data.items():
print("{0:s}={1:s}".format(k, v))
Which outputs:
$ python app.py
nke=nike
tgt=target
aapl=apple
mcd=Mc Donald
rl=Polo Ralph lauren
yhoo=yahoo
googl=google
Update: If you still want to do this with a while loop with a q variant then your data structure will have to be a "list of tuples" -- Where each "tuple" is a key/value pair. e.g: [(1, 2), (3, 4)]
Example: (based on your code more or less)
data = [
('aapl', 'apple'),
('tgt', 'target'),
('nke', 'nike'),
('mcd', 'Mc Donald'),
('googl', 'google'),
('yhoo', 'yahoo'),
('rl', 'Polo Ralph lauren)')
]
q = 0 # counter
while q < len(data):
k, v = data[q] # assign and unpack each tuple (key, value)
print("{0:s}={1:s}".format(k, v))
q += 1
NB: This data structure is mostly the same except that you loose the benefits of being able to do O(1) lookups. Dictionaries/Mappings are more suited to this kind of data structure especially i you intend to perform lookups base don keys.

Related

How to use two given inputs in a function and get the total

So I'm trying to create a function totalcalories(recipes, tcal) where recipes would refer to the ingredients that is going to be provided while tcal is the amount of calories that each ingredient contains...
I have figured out a way to find tcal from the given input but I have no idea how to extract the information from recipes into tcal
So like if the input is
`totalcalories(recipes = ["Pork Stew: Cabbage*5,Carrot*1, Fatty Pork*10",
"Green Salad1:Cabbage*10,Carrot*2,Pineapple*5",
"T-Bone: Carrot*2,Steak Meat*1"],
tcal = [["Cabbage:30", "Carrot:95", "Fatty Pork:2205",
"Pineapple:40", "Steak Meat:215", "Rabbit Meat:225"])
And so I expect the output to return
"22295","690", "405"
So 22295 is the result of the recipe Pork Stew, which is Cabbage(30) from tcal times 5, which is 150, and 1 carrot, which is 95 and 10 Fatty Pork, which is 2205 each. Adding all three numbers give 22295.
The same principle applies for every recipe in recipes, where Green Salad would return 690 and T-bone 405...
What I'm trying to do is to write a function that will return the total calories like the examples I just provided...
Here is my attempt at it... which clearly doesn't work..
def totalcalories(recipes: list[str], tcal: list[str]):
g = []
for x in tcal:
if x in recipes:
g.append(x)
return g
print(totalcalories(["T-Bone", "T-Bone", "Green Salad1"],["Pork Stew:Cabbage*5,Carrot*1,Fatty Pork*10",
"Green Salad1:Cabbage*10,Carrot*2,Pineapple*5",
"T-Bone:Carrot*2,Steak Meat*1"]))
What should I write to make my code work...
Please write the code in the simplest way possible. I would like to take things really slow and understand what the code means so yea, please picture yourself teaching a beginner when you resolve my issue, so that I can also learn along
Thank you!
`
The input data structure is parseable (after all, there's always a way) but would be better if it was in the form of a dictionary. So, this code converts your structure into dictionaries and then goes on to show how much easier it is to process once they're in that form.
recipes = ["Pork Stew: Cabbage*5,Carrot*1, Fatty Pork*10",
"Green Salad1:Cabbage*10,Carrot*2,Pineapple*5",
"T-Bone: Carrot*2,Steak Meat*1"]
calories = ["Cabbage:30", "Carrot:95", "Fatty Pork:2205",
"Pineapple:40", "Steak Meat:215", "Rabbit Meat:225"]
def cdict(): # convert calories list to dictionary
d = dict()
for e in calories:
e_ = e.split(':')
d[e_[0]] = int(e_[1])
return d
def rdict(): # convert recipe list to dictionary
d = dict()
for r in recipes:
i = dict()
r_ = r.split(':')
for c_ in r_[1].split(','):
i_ = c_.split('*')
i[i_[0].strip()] = int(i_[1])
d[r_[0]] = i
return d
recipes_d = rdict()
calories_d = cdict()
for k, v in recipes_d.items():
tcal = 0
for k_, v_ in v.items():
tcal += calories_d[k_] * v_
print(f'Recipe {k} has {tcal} calories')
You can define 2 patterns: one to capture the name of the recipe, the second to capture each single ingredient in the recipe itself.
pattern_recipe = re.compile(r'([^\:]*):.*')
pattern_ingredients = re.compile(r'([^\*\:,]*)\*(\d*),?', re.DOTALL)
Now, process each line of your totalcalories_recipes list create a dictionary which is keyed with the name of the recipe and element the list of ingredients with calories:
recipes_dict = {pattern_recipe.findall(x)[0]:
[(ingredient.strip(), int(calories)) for ingredient, calories in pattern_ingredients.findall(x)]
for x in totalcalories_recipes}
To be clear, the nested list comprehension cleans ingredient name, stripping spaces, and casts calories into int.
At this point, your recipes_dict should look as follows:
{'Pork Stew': [('Cabbage', 5), ('Carrot', 1), ('Fatty Pork', 10)], 'Green Salad1': [('Cabbage', 10), ('Carrot', 2), ('Pineapple', 5)], 'T-Bone': [('Carrot', 2), ('Steak Meat', 1)]}
In a similar fashion, you can get a dictionary from your tcal list:
tcal_dict = {x[0]:int(x[1]) for x in [re.findall("([^\:]*)\:(\d+)", x)[0] for x in tcal]}
Now you are in business! Looping through each recipe in recipes_dict, you can calculate the calories by recipe:
{recipe[0]:sum([ingredient[1] * tcal_dict[ingredient[0]] for ingredient in recipe[1]]) for recipe in recipes_dict.items()}
OUTPUT:
{'Pork Stew': 22295, 'Green Salad1': 690, 'T-Bone': 405}

how to print the list value of the nested dictionary

I have created the following dictionary:
Book_list={
'Fiction': {1001: ['Pride and Prejudice', 'available'],
1002: ['Fahrenheit 451', 'available']},
'Horror': {2001: ['House of leaves', 'available'],
2002: ['The Shinking', 'available']}}
now I want to store the status that is "available" in a variable with its key so that it can be used further for delete or update.
So the output I mean is like:
status={1001:available,1002:available,2001:available,2002:available}
Please help me by telling that how could I get this output.
One approach is to use a dictionary comprehension:
rs = {ii : status for category in Book_list.values() for ii, (name, status) in category.items() if status == "available"}
print(rs)
Output
{1001: 'available', 1002: 'available', 2001: 'available', 2002: 'available'}
The above is equivalent to the followings nested for loops:
for category in Book_list.values():
for ii, (name, status) in category.items():
if status == "available":
rs[ii] = status
For understanding the unpacking expressions such as:
# _, category
# ii, (name, status)
you could read this link. For a general introduction to Python's data structures I suggest reading the documentation.
def receive_available_books(Book_list):
status = {}
for cat in Book_list.values():
for code, book in cat.items():
status[code] = book[1]
return status
Output:
{1001: 'available', 1002: 'available', 2001: 'available', 2002: 'available'}
Using Python 3.10's structural pattern matching, maybe not super appropriate/helpful for this, but I just wanted to try it :-)
rs = {}
for category in Book_list.values():
for item in category.items():
match item:
case ii, [_, 'available' as status]:
rs[ii] = status
(code adapted from Dani's)
With this code you get almost exactly the output you want:
d={}
for a in Book_list.values():
for x,y in a.items():
d[x]=y[1]
print("status=", d)
You could also, of course, assign d to your a status variable.
This code just creates first an empty d as dict and then fills it with data and finally prints it. To fill d with data, a, x and y take different values while walking (iterating) over your object:
a: For example {1001: ['Pride and Prejudice', 'available'], 1002: ['Fahrenheit 451', 'available']}
x: For example 1001
y: For example ['Pride and Prejudice', 'available']
y[1] would then be 'available'

How to check a list for duplicates and add values if there are any?

I'm totally beginner with coding and just need help with some stuff.
My dream was to write a smart shopping list that automatically detects duplicates and increases the weight of duplicate products.
I get the shopping list from an external file which has the following form:
weight\n
ingredient\n
eg.
60
eggs
120
beef meat
25
pasta
120
eggs
etc...
After converting this files to dictionaries by this code:
final_list = []
def get_list(day_list):
for day in range(len(day_list)):
day += 1
day_to_open = f'Days/day{str(day)}.txt'
with open(day_to_open, 'r') as file:
day1 = file.readlines()
day1 = [item.rstrip() for item in day1]
x = 0
y = 1
list = []
for item in range(0, len(day1), 2):
dictio = {day1[y]: day1[x]}
x += 2
y += 2
list.append(dictio)
final_list.append(list)
list = []
for item in final_list:
list += item
return list
days = [1, 2, 3]
list = get_list(day_list=days)
Finally I get list of dictionaries like that:
[{'eggs': '60'}, {'beef meat': '120'}, {'pasta': '25'}, {'eggs': '120'}]
How can I iterate through the dictionary to check if any products are repeating, and if so leave one with the added weight?
For three weeks I have been trying to solve it, unfortunately to no avail.
Thank you very much for all your help!
#Edit
my goal is to make it look like this:
[{'eggs': 180}, {'beef meat': 120}, {'pasta': 25}]
#egg weight added (120 + 60)#
lis = [{'eggs': '60'}, {'beef meat': '120'}, {'pasta': '25'}, {'eggs': '120'}]
# make 1 dict from list of dicts and update max value
new = {}
for d in lis:
for k, v in d.items():
if (k not in new) or (int(v) > int(new[k])):
new[k] = v
# rebuild list of dicts
lis = [{k:v} for k, v in new.items()]
print(lis)
# [{'eggs': '120'}, {'beef meat': '120'}, {'pasta': '25'}]
As ShadowRanger has pointed out, it's not common practice to have a list of multiple dictionaries as you have done. Dictionaries are very useful if used correctly.
I'm not entirely sure the structure of the files you are reading, so I will just explain a way forward and leave it up to you to implement it. What I would suggest is that you first initiate a dictionary with all the necessary keys (ingredients in your case) with each of the values set to 0 (as an integer or float, rather than a string), so you would get a dictionary like this:
shopping_list = {'eggs': 0, 'beef meat': 0, 'pasta': 0}
Then, you will be able to access each of the values by calling the shopping_list dictionary and specifying the key of interest. For example, if you wanted to print the value of eggs, you would write:
print(shopping_list['eggs']) # this would return 0
You can then easily increase/decrease a value of interest; for example, to add 10 to pasta, you would write:
shopping_list['eggs'] += 10
Using this method, you can then iterate through each of your items, select the ingredient of interest and add the weight. So if you have duplicates, it will just add to the same ingredient. Again, I'm not sure the structure of the files you are reading, but it would be something along the lines of:
for ingredient, weight in file:
shopping_list[ingredient] += weight
Good luck for your dream - all the best!

pandas summing up columns by group [duplicate]

I often use pandas groupby to generate stacked tables. But then I often want to output the resulting nested relations to json. Is there any way to extract a nested json filed from the stacked table it produces?
Let's say I have a df like:
year office candidate amount
2010 mayor joe smith 100.00
2010 mayor jay gould 12.00
2010 govnr pati mara 500.00
2010 govnr jess rapp 50.00
2010 govnr jess rapp 30.00
I can do:
grouped = df.groupby('year', 'office', 'candidate').sum()
print grouped
amount
year office candidate
2010 mayor joe smith 100
jay gould 12
govnr pati mara 500
jess rapp 80
Beautiful! Of course, what I'd real like to do is get nested json via a command along the lines of grouped.to_json. But that feature isn't available. Any workarounds?
So, what I really want is something like:
{"2010": {"mayor": [
{"joe smith": 100},
{"jay gould": 12}
]
},
{"govnr": [
{"pati mara":500},
{"jess rapp": 80}
]
}
}
Don
I don't think think there is anything built-in to pandas to create a nested dictionary of the data. Below is some code that should work in general for a series with a MultiIndex, using a defaultdict
The nesting code iterates through each level of the MultIndex, adding layers to the dictionary until the deepest layer is assigned to the Series value.
In [99]: from collections import defaultdict
In [100]: results = defaultdict(lambda: defaultdict(dict))
In [101]: for index, value in grouped.itertuples():
...: for i, key in enumerate(index):
...: if i == 0:
...: nested = results[key]
...: elif i == len(index) - 1:
...: nested[key] = value
...: else:
...: nested = nested[key]
In [102]: results
Out[102]: defaultdict(<function <lambda> at 0x7ff17c76d1b8>, {2010: defaultdict(<type 'dict'>, {'govnr': {'pati mara': 500.0, 'jess rapp': 80.0}, 'mayor': {'joe smith': 100.0, 'jay gould': 12.0}})})
In [106]: print json.dumps(results, indent=4)
{
"2010": {
"govnr": {
"pati mara": 500.0,
"jess rapp": 80.0
},
"mayor": {
"joe smith": 100.0,
"jay gould": 12.0
}
}
}
I had a look at the solution above and figured out that it only works for 3 levels of nesting. This solution will work for any number of levels.
import json
levels = len(grouped.index.levels)
dicts = [{} for i in range(levels)]
last_index = None
for index,value in grouped.itertuples():
if not last_index:
last_index = index
for (ii,(i,j)) in enumerate(zip(index, last_index)):
if not i == j:
ii = levels - ii -1
dicts[:ii] = [{} for _ in dicts[:ii]]
break
for i, key in enumerate(reversed(index)):
dicts[i][key] = value
value = dicts[i]
last_index = index
result = json.dumps(dicts[-1])
Here is a generic recursive solution for this problem:
def df_to_dict(df):
if df.ndim == 1:
return df.to_dict()
ret = {}
for key in df.index.get_level_values(0):
sub_df = df.xs(key)
ret[key] = df_to_dict(sub_df)
return ret
I'm aware this is an old question, but I came across the same issue recently. Here's my solution. I borrowed a lot of stuff from chrisb's example (Thank you!).
This has the advantage that you can pass a lambda to get the final value from whatever enumerable you want, as well as for each group.
from collections import defaultdict
def dict_from_enumerable(enumerable, final_value, *groups):
d = defaultdict(lambda: defaultdict(dict))
group_count = len(groups)
for item in enumerable:
nested = d
item_result = final_value(item) if callable(final_value) else item.get(final_value)
for i, group in enumerate(groups, start=1):
group_val = str(group(item) if callable(group) else item.get(group))
if i == group_count:
nested[group_val] = item_result
else:
nested = nested[group_val]
return d
In the question, you'd call this function like:
dict_from_enumerable(grouped.itertuples(), 'amount', 'year', 'office', 'candidate')
The first argument can be an array of data as well, not even requiring pandas.

Check if list element in list is in another list in list in Python

Given the data below, how would I print elements of a list within a list that were present within another list within a different list?
Example;
a = [['P101','John','Jones','100'], ['P102','Steve','Woodhouse','500'], ['P103','Ben','Jacobs','60']]
b = [['P101','John','Jones','250'], ['P102','Steve','Woodhouse','500']
I would like to print 'John Jones' & 'Steve Woodhouse' even though 'John Jones''s list is slightly different (his ID 'P101' still appears in both lists). I would also like to print 'Steve Woodhouse' but not 'Ben Jacobs', because he is not present in both lists.
One of the approaches can be. This checks if the same ID is present in both the lists. (Not a efficient one)
>>> for i in a:
... if i[0] in (j[0] for j in b):
... print("{} {}".format(i[1],i[2]))
...
John Jones
Steve Woodhouse
You could create dictionaries instead and then intersect the keys using the viewkeys function like so:
a = [['P101','John','Jones','100'], ['P102','Steve','Woodhouse','500'], ['P103','Ben','Jacobs','60']]
b = [['P101','John','Jones','250'], ['P102','Steve','Woodhouse','500']]
ad = { p[0]: "{} {}".format(p[1],p[2]) for p in a}
bd = { p[0]: "{} {}".format(p[1],p[2]) for p in b}
common_id = ad.viewkeys() & bd.viewkeys()
for id in common_id:
print ad[id]
Live example

Categories