I was wondering how I could take this user input(below) and just modify the item that is already in the list. If the user does not input the same item as show in the list then just add the input as a new grocery item.
List
inventory = [['Milk, 3.99, 25'],
['Bread, 1.99, 35'],
['Eggs, 1.99, 50'],
['Flour, 0.52, 20'],
['Rice, 0.72, 35']]
Input
modItem = input("Enter the name of an existing item you want to modify:")
modPrice = input("Enter the new price of the item:")
modStock = input("Enter the new stock of the item:")
inventory.append([modItem, modPrice, modStock])
Try to check if the item already exists using a simple function:
def check_inventory(modItem, inventory):
try:
for item in inventory:
if modItem == item[0].split(', ')[0]:
return True
except:
pass
return False
...
# then, you can call your function
if (check_inventory(modItem, inventory)):
inventory.append([modItem, modPrice, modStock])
The second approach is converting your list into a dict. I would recommend this.
You could use a dict
inventory = {'Milk': [3.99, 25],
'Bread': [1.99, 35],
'Eggs': [1.99, 50],
'Flour': [0.52, 20],
'Rice': [0.72, 35]}
modItem = input("Enter the name of an existing item you want to modify:")
modPrice = float(input("Enter the new price of the item:"))
modStock = int(input("Enter the new stock of the item:"))
Enter the name of an existing item you want to modify:Milk
Enter the new price of the item:10
Enter the new stock of the item:12
If item already exists, it will be replaced, else a new key-value pair would be added
inventory[modItem] = [modPrice, modStock]
inventory
{'Milk': [10.0, 12],
'Bread': [1.99, 35],
'Eggs': [1.99, 50],
'Flour': [0.52, 20],
'Rice': [0.72, 35]}
Your inventory list was malformed. Here's code that does what you want in the most direct way, given your existing code and the corrected version of your data:
inventory = [['Milk', '3.99', '25'],
['Bread', '1.99', '35'],
['Eggs', '1.99', '50'],
['Flour', '0.52', '20'],
['Rice', '0.72', '35']]
modItem = input("Enter the name of an existing item you want to modify:")
modPrice = input("Enter the new price of the item:")
modStock = input("Enter the new stock of the item:")
for item in inventory:
if item[0] == modItem:
item[1] = modPrice
item[2] = modStock
break
else:
inventory.append([modItem, modPrice, modStock])
This code loops over the existing inventory, looking for the item the user entered the name of. If the name is found, the item containing that item is updated with the new price and quantity. If no existing item is found, then a new item is created and added.
You could use enumerate and modify the list while iterating over the elements:
inventory = [['Milk, 3.99, 25'],
['Bread, 1.99, 35'],
['Eggs, 1.99, 50'],
['Flour, 0.52, 20'],
['Rice, 0.72, 35']]
modItem = 'Milk'
modPrice = 4
modStock = 30
found = False
for idx, elt in enumerate(inventory):
if modItem in elt[0]:
inventory[idx] = [f"{modItem}, {modPrice}, {modStock}"] # modify the element at the found index
found = True
break
if not found:
inventory.append([f"{modItem}, {modPrice}, {modStock}"])
print(inventory)
Output:
[['Milk, 4, 30'], ['Bread, 1.99, 35'], ['Eggs, 1.99, 50'], ['Flour, 0.52, 20'], ['Rice, 0.72, 35']]
Further, I would suggest to keep the inner list as the list of elements. Currently, it is just a single element with a str object.
inventory = [['Milk', 3.99, 25],
['Bread', 1.99, 35],
['Eggs', 1.99, 50],
['Flour', 0.52, 20],
['Rice', 0.72, 35]]
found = False
for idx, elt in enumerate(inventory):
if modItem == elt[0]:
inventory[idx] = [modItem, modPrice, modStock]
found = True
break
if not found:
inventory.append([modItem, modPrice, modStock])
print(inventory)
Output:
[['Milk', 4, 30], ['Bread', 1.99, 35], ['Eggs', 1.99, 50], ['Flour', 0.52, 20], ['Rice', 0.72, 35]]
Related
I am converting information about a delivery from a file given to me, it contains information like this:
name, item_number, item_number, item_number
for example
Joe, 2, 22, 10, 17
The issue is whenever i try to replace the number in the line, with a value associated with the key, which is indetical to the item_number from the file, it returns for example the value associated with 2, x2 times instead of the value associated with 22.
import sys
f = open("testFil.txt", "r")
list_of_lists = []
items = {
1: "Cigaretter",
2: "Snus",
3: "Kaffe",
4: "Te",
5: "Solbriller",
6: "Mørk Chokolade",
7: "Kiks",
8: "Harebo Mix",
9: "Salt Chips",
10: "Pepper Chips",
11: "Sour Cream Chips",
12: "Oreo",
13: "Ritter Sport",
14: "Chokolade Kiks",
15: "Mælk",
16: "Sukker",
17: "Brød",
18: "Kuglepen",
19: "Juice",
20: "Avis",
21: "Toilet Papir",
22: "Tandbørste",
23: "Kondomer",
24: "Tandpasta",
25: "Køkkenrulle"}
with open("testFil.txt", "r") as f:
for line in f:
line = line.replace("\n","")
for i in items:
line = line.replace(str(i), items[i])
list_of_lists.append(line.split(", "))
for i in list_of_lists:
for j in i:
if i.count(j) > 1:
i[i.index(j)] = str(i.count(j)) + "x " + j
for k in range(i.count(j)):
i.remove(j)
customer_count = -1
def last_customer():
print("This is the last order")
print(list_of_lists[next_customer()])
def luk_programmet():
sys.exit()
def next_customer():
global customer_count
customer_count += 1
return customer_count
def print_customer():
a = input("")
if a == "Next Order":
if customer_count == len(list_of_lists) - 2:
print("This is the last order")
print(list_of_lists[next_customer()])
luk_programmet()
else:
try:
print(list_of_lists[next_customer()])
except IndexError:
print("This is the last order")
luk_programmet()
elif a == "/close the program":
luk_programmet()
else:
print("You typed it wrong.")
print_customer()
#Prints the customer list
print("Write 'Next Order' to recieve the next order")
for i in range(len(list_of_lists)):
if print_customer() == "Done":
sys.exit()
print_customer()
The txt file:
Joe, 1, 2, 1, 8
Micky, 19, 19, 15, 13
Berta, 4, 3, 3, 3
Frede, 24, 22, 8, 2
per, 1, 9, 18, 24
I have tried making the key into a string, in the hopes that would help, but that didn't work out.
The core problem you have is that you're performing string replacement, which as you've observed, replaces every instance of "2" with a value.
To illustrate:
>>> "222".replace("2", "something")
'somethingsomethingsomething'
So, what's a better approach?
Given the following file contents as a source:
Joe, 1, 2, 1, 8
Micky, 19, 19, 15, 13
Berta, 4, 3, 3, 3, 3
Frede, 24, 22, 8, 2
per, 1, 9, 18, 24, 12, 22, 1, 23
We can use Python's inbuild csv library to parse the file contents, and do some funky stuff with csv.DictReader:
with open("testFil.txt") as f:
reader = csv.DictReader(f, fieldnames=["person"], restkey="items", skipinitialspace=True)
for row in reader:
item_names = []
for item in row["items"]:
item_name = items[int(item)]
item_names.append(item_name)
row["item_names"] = item_names
print(row)
Few things to highlight:
We tell the DictReader that there's only one column (the first one) with the fieldnames arugment.
The restval argument is the name given to the un-named columns (which will conveniently be a list of values):
The optional restval parameter specifies the value to be written if the dictionary is missing a key in fieldnames
We use skipinitialspace as the values in the input have leading spaces between the commas!
We can then perform a lookup of the exact value, rather than a replacement!
I have chosen to build up the item list as a separate list which I add back on to the row.
The output from the above code is this:
{'person': 'Joe', 'items': ['1', '2', '1', '8'], 'item_names': ['Cigaretter', 'Snus', 'Cigaretter', 'Harebo Mix']}
{'person': 'Micky', 'items': ['19', '19', '15', '13'], 'item_names': ['Juice', 'Juice', 'Mælk', 'Ritter Sport']}
{'person': 'Berta', 'items': ['4', '3', '3', '3', '3'], 'item_names': ['Te', 'Kaffe', 'Kaffe', 'Kaffe', 'Kaffe']}
{'person': 'Frede', 'items': ['24', '22', '8', '2'], 'item_names': ['Tandpasta', 'Tandbørste', 'Harebo Mix', 'Snus']}
{'person': 'per', 'items': ['1', '9', '18', '24', '12', '22', '1', '23'], 'item_names': ['Cigaretter', 'Salt Chips', 'Kuglepen', 'Tandpasta', 'Oreo', 'Tandbørste', 'Cigaretter', 'Kondomer']}
Hi I have this calculation but I am failing to understand how this line [array([1050885., 1068309., 1085733., 1103157., 1120581.]) of the output is calculated, please explain.
creating sample data:
#creating sample data:
data1 = pd.DataFrame({"client": ['x1', 'x2'],
"cat": ['Bb', 'Ee'],
"amt": [1000,300],
"time":[2, 3],
"group":[10, 25]})
listc = ['Aa','Bb','Cc','Dd','Ee']
val1 = pd.DataFrame({'time': [1, 2, 3],
'lim %': [0.1, 0.11, 0.112]})
val2 = pd.concat([pd.DataFrame({'group':g, 'perc': 0.99, 'time':range(1, 11)}
for g in data1['group'].unique())]).explode('time')
mat = np.arange(75).reshape(3,5,5)
vals = [val1, val2]
data1['cat'] = pd.Categorical(data1['cat'],
categories=listc,
ordered=True).codes
for i in range(len(vals)):
if 'group' in vals[i].columns:
vals[i] = vals[i].set_index(['time', 'group'])
else:
vals[i] = vals[i].set_index(['time'])
#nested loop calculation
calc = {}
for client, cat, amt, start, group in data1.itertuples(name=None, index=False):
for time in range(start, len(mat)+1):
if time == start:
calc[client] = [[amt * mat[time-1, cat, :]]]
else:
calc[client].append([calc[client][-1][-1] # mat[time-1]])
for valcal in vals:
if isinstance(valcal.index, pd.MultiIndex):
value = valcal.loc[(time, group)].iat[0]
else:
value = valcal.loc[time].iat[0]
calc[client][-1].append(value * calc[client][-1][-1])
output:
{'x1': [[array([30000, 31000, 32000, 33000, 34000]),
array([3300., 3410., 3520., 3630., 3740.]),
array([3267. , 3375.9, 3484.8, 3593.7, 3702.6])],
[array([1050885., 1068309., 1085733., 1103157., 1120581.]), #how is this line calculated?
array([117699.12 , 119650.608, 121602.096, 123553.584, 125505.072]),
array([116522.1288 , 118454.10192, 120386.07504, 122318.04816,
124250.02128])]],
'x2': [[array([21000, 21300, 21600, 21900, 22200]),
array([2352. , 2385.6, 2419.2, 2452.8, 2486.4]),
array([2328.48 , 2361.744, 2395.008, 2428.272, 2461.536])]]}
what I need the calc for this line to be is:
[array([1050885., 1068309., 1085733., 1103157., 1120581.])
it should take array([3267. , 3375.9, 3484.8, 3593.7, 3702.6])] multiplied by mat at time 3, how can I get it to do this?
I have a function as below & the inputs are given as:
Inputs:
items = ['17','2','8','34']
item_mapping = {'17':['17','5','8'],'2':['2','0'],'8':['8','2','90'],'34':['34','33']}
item_history = {'India': {'17': '2021-11-14',
'2': '2021-11-10',
'8': '2021-11-8',
'34': '2021-09-22',
'90': '2021-11-5',
'33': '2021-11-11',
'56': '2021-09-22',
'0': '2021-11-3',
'5': '2021-11-8']},
'USA': {'17': '2021-11-10',
'2': '2021-11-20',
'8': '2021-11-25',
'34': '2021-09-22',
'90': '2021-11-6',
'33': '2021-11-30',
'56': '2021-09-22',
'0': '2021-11-1',
'5': '2021-11-13']
}
The function:
def get_results(items,item_mapping,item_history):
result_list = []
for item in items:
current_line = [item]
if item in item_mapping:
identical_item_list = item_mapping[item]
else:
identical_item_list = [item]
for area, history in item_history.items():
item_history_list = []
for identical_item in identical_item_list:
if identical_item in items and identical_item in history:
item_history_list.append([identical_item, history[identical_item]])
if len(item_history_list) > 0:
sorted_item_history_list = sorted(item_history_list, key=lambda x: x[1], reverse=True)
selected_item = sorted_item_history_list[0][0]
current_line += [area, selected_item]
else:
pass
master_item_to_item_list.append(" ".join(current_line))
return result_list
For each item in list - 'items', I have the list of items identical to it in the dictionary -'item_mapping'.
I also have a dictionary - 'item_history' which has the dates on which items were sold in different regions.
The objective I am trying to achieve is, for each item, I would like to get the latest sold similar item in each region.
For example, take item 17:
The similar items are ['17','5','8']
For region 'India', the latest sold similar item, for item 17 is 17.
For region 'USA', it is '8'.
Hence the output line will be : ['17' 'India' '17' 'USA' '8']
Similarly, I want to get for all items and write lines to a text file.
When I have hundreds of thousands of items, it takes hours to do this multiple for loops with sorting and searches. How can I optimize this code? Any other data structures I can use?
I tried implementing multiprocessing like below: but it's still equally slow.
def get_results(item,item_mapping,item_history):
result_list = []
current_line = [item]
if item in item_mapping:
identical_item_list = item_mapping[item]
else:
identical_item_list = [item]
for area, history in item_history.items():
item_history_list = []
for identical_item in identical_item_list:
if identical_item in items and identical_item in history:
item_history_list.append([identical_item, history[identical_item]])
if len(item_history_list) > 0:
sorted_item_history_list = sorted(item_history_list, key=lambda x: x[1], reverse=True)
selected_item = sorted_item_history_list[0][0]
current_line += [area, selected_item]
else:
pass
master_item_to_item_list.append(" ".join(current_line))
return result_list
import multiprocessing as mp
import functools
with mp.Pool(28) as pool:
result = pool.map(functools.partial(get_results,item_mapping=item_mapping,item_history=item_history), items)
wanna write a code that would add to burgerlist the items of my_order with the following order: first and last element of burgerlist should be bread, second and pre-last element should be mayonnaise(if it exist among the arguments while calling function), then beef / chicken, then vegitables.
pls help to understand what to change here
def my_odrer(*g):
ingredients = [['long_bread', 'circle_bread'], ['mayonnaise', 'ketchup'], ['beef', 'chicken'],
['cucumber', 'tomato', 'onion']]
burgerlist = []
for i in g:
if i in ingredients[0]:
burgerlist.insert(0, i)
elif i in ingredients[1]:
burgerlist.insert(1, i)
elif i in ingredients[2]:
burgerlist.append(i)
elif i in ingredients[3]:
burgerlist.append(i)
if burgerlist[1] == 'mayonnaise':
burgerlist.append(burgerlist[1])
burgerlist.append(burgerlist[0])
return burgerlist
print(my_odrer('circle_bread', 'beef', 'tomato', 'mayonnaise', 'ketchup'))
the output is: ['circle_bread', 'ketchup', 'mayonnaise', 'beef', 'tomato', 'circle_bread']
but I want to get: ['circle_bread', 'mayonnaise', 'ketchup', 'beef', 'tomato','mayonnaise', 'circle_bread']
Create 3 lists containing the ingredients that should be at the beginning, middle, and end. Then concatenate them to produce the final result.
def my_odrer(*g):
breads = {'long_bread', 'circle_bread'}
condiments = {'ketchup'} # mayonnaise not included, since it's handled specially
meats = {'beef', 'chicken'}
vegetables = {'cucumber', 'tomato', 'onion'}
beginning = []
middle = []
end = []
for item in g:
if item in breads:
beginning.append(item)
end.append(item)
if "mayonnaise" in g:
beginning.append("mayonnaise")
end.insert(-1, "mayonnaise")
for item in g:
if item in condiments:
middle.append(item)
for item in g:
if item in meats:
middle.append(item)
for item in g:
if item in vegetables:
middle.append(item)
return beginning + middle + end
It works after I added an additional condition in your final if statement.
def my_odrer(*g):
ingredients = [['long_bread', 'circle_bread'], ['mayonnaise', 'ketchup'], ['beef', 'chicken'],
['cucumber', 'tomato', 'onion']]
burgerlist = []
for i in g:
if i in ingredients[0]:
burgerlist.insert(0, i)
elif i in ingredients[1]:
burgerlist.insert(1, i)
elif i in ingredients[2]:
burgerlist.append(i)
elif i in ingredients[3]:
burgerlist.append(i)
if burgerlist[1] == 'mayonnaise':
burgerlist.append(burgerlist[1])
elif burgerlist[2] == 'mayonnaise':
burgerlist[1], burgerlist[2] = burgerlist[2], burgerlist[1]
burgerlist.append(burgerlist[1])
burgerlist.append(burgerlist[0])
return burgerlist
I'm trying to cycle through 2 lists using for loops to calculate the sum for each unique reference. I suppose I'm looking for a pythonic sumif!
# list of data ("user_ID", "contract_Number", "weight", "type")
list1 = [
('1','261','6.2','Input'),
('1','262','7.2','Input'),
('1','263','5.2','Input'),
('1','264','8.2','Input'),
('1','261','3.2','Input'),
('1','262','2.2','Input'),
('1','262','7.2','Input'),
('1','263','4.2','Input'),
('1','264','6.2','Input'),
('1','265','6.2','Input'),
('1','261','9.2','Input'),
('1','261','10.2','Input')
]
contract_list = []
# create a list of contract numbers
for data_row in list1:
if data_row[0] == "1" and data_row[3] == "Input":
contract_list.append(data_row[1])
#remove duplication - left with a list of unique contract numbers
contract_list = list(dict.fromkeys(contract_list))
print(contract_list)
# I'm trying this...[28.6, 16.6, 9.4, 14.4, 6.2]
tally_list = []
tally = 0
for c in contract_list:
for l in list1:
if data_row[0] == '1' and data_row[1] == contract_list[0]:
tally = tally + float(data_row[2])
tally_list.append(tally)
print(tally_list)
I'm expecting...
['261', '262', '263', '264', '265']
[28.6, 16.6, 9.4, 14.4, 6.2]
I'm getting...
['261', '262', '263', '264', '265']
[122.40000000000002, 244.7999999999999, 367.19999999999976, 489.5999999999996, 612.0]
# I'm trying this...[28.6, 16.6, 9.4, 14.4, 6.2]
tally_list = []
tally = 0
for c in contract_list:
for l in list1: #<----------
if data_row[0] == '1' and data_row[1] == contract_list[0]:
tally = tally + float(data_row[2])
tally_list.append(tally)
In the marked row, it looks like you want to use the data_row variable instead of l
Actually, try this, you need to additionally reset tally and also use c instead of contract_list[0] in the final if statement.
# I'm trying this...[28.6, 16.6, 9.4, 14.4, 6.2]
tally_list = []
tally = 0
for c in contract_list:
for data_row in list1:
if data_row[0] == '1' and data_row[1] == c: #<----
tally = tally + float(data_row[2])
tally_list.append(tally)
tally=0 #<---
print(tally_list)
Just another approach using a defaultdict
from collections import defaultdict
list1 = [
('1','261','6.2','Input'),
('1','262','7.2','Input'),
('1','263','5.2','Input'),
('1','264','8.2','Input'),
('1','261','3.2','Input'),
('1','262','2.2','Input'),
('1','262','7.2','Input'),
('1','263','4.2','Input'),
('1','264','6.2','Input'),
('1','265','6.2','Input'),
('1','261','9.2','Input'),
('1','261','10.2','Input')
]
d = defaultdict(int)
for tup in list1:
if tup[0] == '1' and tup[3] == 'Input':
d[tup[1]] += float(tup[2])
contract_list = list(d)
print(contract_list)
tally_list = [format(v, '.1f') for v in d.values()]
print(tally_list)
Output:
['261', '262', '263', '264', '265']
['28.8', '16.6', '9.4', '14.4', '6.2']