To many print results - for key in dict - python

Good morning everyone,
There are a number of posts on here somewhat related to this however I am newer and a hands on learner so it's difficult to grasp the solutions offered on other peoples coding when I don't necessarily know their end goal. This is the first time I have tried to apply my coding skills (or lack thereof :D) but I have been working through m1mo and reading/watching an assortment of guides/tutorials the last couple of months. So yes my code may look goofy to a lot of you but got to start somewhere!
Goal: I want to pull the dictionary value from product_dict of the key that is in the c_item_number_one, which this code does successfully, but if the key does not appear in the dictionary then I want to print("Not in dictionary")
Issue: While the code does provide the dictionary value based on the key there will be times when the c_item_number_one does not include a valid key. When this happens, I want to know by print("Not in dictionary"). Currently this code will print "Not in dictionary" for every single dictionary entry that does not appear in my product_dict. I only want it to tell me once in the event it does not appear a single time.
There will also be times, like in this example, where multiple keys are found within the dictionary, this is okay. I want it to print all of these instances as I will be adding further validation when this occurs in later code.
Note that the below is a small sample of the actual dictionary and that I have roughly 1200 entries in reality with more to be added as time goes on.
"Product" is only one of a dozen categories I need to pull from descriptions so any help here will greatly help me towards the end game and be very much appreciated!
product_dict = {
'BEND': 'BEND',
'FABRICATE SPOOL': 'PIPE SPOOL',
'STUB-END': 'STUB END',
'GSK': 'GASKET',
'SA-106': 'PIPE',
'PIPE': 'PIPE',
}
c_item_number_one = '12",PIPE , GR. B, SCH 40, WALL SMLS'
#Product for Item One
def item_one_product():
found = True
for key in product_dict:
if key in c_item_number_one:
item_number_one_product = product_dict[key]
print(item_number_one_product)
else:
found = False
print("Not in dictionary")
item_one_product()
It prints:
Not in dictionary
Not in dictionary
Not in dictionary
Not in dictionary
PIPE
PIPE

You were close, check this:
#Product for Item One
def item_one_product():
not_found = True
for key in product_dict:
if key in c_item_number_one:
item_number_one_product = product_dict[key]
print(item_number_one_product)
not_found = False
if not_found:
print("Not in dictionary")
item_one_product()

Related

Using a key taken from an input and using it to recall a value

The project is based on a cashier. When an input is accepted, it gets stored. I have used this to determine whether an item is in the dictionary or not.
I am currently stuck on how to implement the input as a key to recall the corresponding value in a defined dictionary.
Is there any way to do this using the tools I've used, or is a more complicated function required? My code is underneath, and the very last line seems to be the problem. Thanks.
my_dictionary = {"Chips", 1}
#Taking order
order = input("What do you want? \n")
#Recalling order
if order in my_dictionary:
print(f"Okay you want {order}")
else:
print("We dont have that please leave")
exit()
#Gving price
print(my_dictionary["order"])
Below is the code I have written that checks if the order the user inputs is:
In your dictionary.
In stock.
Python is case sensitive so I have added the .title() method to the user input to convert the string to title case. This is because the 'Chips' in your dictionary is also in title case.
my_dictionary = {
"Chips" : 1
}
order = input("What do you want?\n").title()
if order in my_dictionary:
if my_dictionary[order] == 0:
print("We don't have that, please leave.")
else:
print(f"Okay you want, {order}")
Hopefully this helps :)
remove the " " around order like: my_dictionary[order] in your last print() function.
I've opted to use this code for the time being, having solved the issue:
my_dictionary = {"chips", 1}
order = input("What do you want?\n").lower()
if order in my_dictionary:
print(f"Ok you want {order}")
else:
print("We dont have that, leave")

Iterate over Python list with clear code - rewriting functions

I've followed a tutorial to write a Flask REST API and have a special request about a Python code.
The offered code is following:
# data list is where my objects are stored
def put_one(name):
list_by_id = [list for list in data_list if list['name'] == name]
list_by_id[0]['name'] = [new_name]
print({'list_by_id' : list_by_id[0]})
It works, which is nice, and even though I understand what line 2 is doing, I would like to rewrite it in a way that it's clear how the function iterates over the different lists. I already have an approach but it returns Key Error: 0
def put(name):
list_by_id = []
list = []
for list in data_list:
if(list['name'] == name):
list_by_id = list
list_by_id[0]['name'] = request.json['name']
return jsonify({'list_by_id' : list_by_id[0]})
My goal with this is also to be able to put other elements, that don't necessarily have the type 'name'. If I get to rewrite the function in an other way I'll be more likely to adapt it to my needs.
I've looked for tools to convert one way of coding into the other and answers in forums before coming here and couldn't find it.
It may not be beatiful code, but it gets the job done:
def put(value):
for i in range(len(data_list)):
key_list = list(data_list[i].keys())
if data_list[i][key_list[0]] == value:
print(f"old value: {key_list[0], data_list[i][key_list[0]]}")
data_list[i][key_list[0]] = request.json[test_key]
print(f"new value: {key_list[0], data_list[i][key_list[0]]}")
break
Now it doesn't matter what the key value is, with this iteration the method will only change the value when it finds in the data_list. Before the code breaked at every iteration cause the keys were different and they played a role.

why is the loop repeating (seemingly randomly) after the function should have completed?

I have been trying to write a programme to draw pairs of names 'out of a hat'. Its for family present buying and therefore has some 'exemptions' due to living in the same house. Each person on the list of names will buy a present for, and be bought a present by, someone else on the list (names_in_hat in code below).
The code below has several print calls there to help me work out what was going on.
The code seems to run fine (rejecting pairs on the exemption list as they appear and re-drawing) until all names on the list appear without hitting any exemptions. At this point i was expecting the programe to just finish (as the for loop has hit the end of its range), but i periodically see several more - seemingly random itterations of the loop appearing, and i cant work out why...?
I have now got the programme working as i want it, after adding raise SystemExit(0) on line 47, which (as i understand it) just stops the programme as soon as the full list of paired names has been generated.
Anyway, can anyone tell me why the original version (as below, with the raise SystemExit(0) commented out) carrys on beyond what i was expecting to be the final list?
Thanks
# script to draw pairs of names 'from a hat' for a 'secret' santa
# certain pairs are not allowed
import random
# names for the draw
names_in_hat = ['Ross', 'Rachel', 'Monica', 'Chandler', 'Joey', 'Phoebe']
# the pairs not allowed
# note this only evaluates pairs EXACTLY as they are shown, i.e.
# ['Ross', 'Rachel'] isnt same as ['Rachel', 'Ross']
exclusions = [['Ross', 'Rachel'],['Monica', 'Chandler'], ['Joey', 'Phoebe']]
# function to make the draw
def draw(names):
random.shuffle(names) #shuffle the deck
#print(names)
# create empty list to store the drawn pairs
pairs = []
#select pairs of names and check if they are in the exclusions list
for i in range(len(names)):
if i == len(names)-1:
D1 = names[i]
D2 = names[0]
else:
D1 = names[i]
D2 = names[i + 1]
# THere will be a more elegant way of checkin the selection, regardless of order...
select_a = [D1, D2]
select_b = [D2, D1]
if select_a in exclusions or select_b in exclusions:
print("**PAIR", select_a, "NOT ALLOWED**")
print("")
draw(names) #re-shuffle and re-draw
else:
pairs.append(select_a)
print(i, pairs)
#print(pairs)
#raise SystemExit(0)
draw(names_in_hat)
As others suggested in comments, you have an issue with the recursive call being in a loop that usually doesn't finish right afterwards. Introduce a break or return right after the recursive call, and pass the list as parameter to function (add another formal parameter for it) (lists are passed by reference and are mutable).

Constantly getting IndexError and am unsure why in Python

I am new to python and really programming in general and am learning python through a website called rosalind.info, which is a website that aims to teach through problem solving.
Here is the problem, wherein you're asked to calculate the percentage of guanine and thymine to the string of DNA given to for each ID, then return the ID of the sample with the greatest percentage.
I'm working on the sample problem on the page and am experiencing some difficulty. I know my code is probably really inefficient and cumbersome but I take it that's to be expected for those who are new to programming.
Anyway, here is my code.
gc = open("rosalind_gcsamp.txt","r")
biz = gc.readlines()
i = 0
gcc = 0
d = {}
for i in xrange(biz.__len__()):
if biz[i].startswith(">"):
biz[i] = biz[i].replace("\n","")
biz[i+1] = biz[i+1].replace("\n","") + biz[i+2].replace("\n","")
del biz[i+2]
What I'm trying to accomplish here is, given input such as this:
>Rosalind_6404
CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCC
TCCCACTAATAATTCTGAGG
Break what's given into a list based on the lines and concatenate the two lines of DNA like so:
['>Rosalind_6404', 'CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCCTCCCACTAATAATTCTGAGG', 'TCCCACTAATAATTCTGAGG\n']
And delete the entry two indices after the ID, which is >Rosalind. What I do with it later I still need to figure out.
However, I keep getting an index error and can't, for the life of me, figure out why. I'm sure it's a trivial reason, I just need some help.
I've even attempted the following to limited success:
for i in xrange(biz.__len__()):
if biz[i].startswith(">"):
biz[i] = biz[i].replace("\n","")
biz[i+1] = biz[i+1].replace("\n","") + biz[i+2].replace("\n","")
elif biz[i].startswith("A" or "C" or "G" or "T") and biz[i+1].startswith(">"):
del biz[i]
which still gives me an index error but at least gives me the biz value I want.
Thanks in advance.
It is very easy do with itertools.groupby using lines that start with > as the keys and as the delimiters:
from itertools import groupby
with open("rosalind_gcsamp.txt","r") as gc:
# group elements using lines that start with ">" as the delimiter
groups = groupby(gc, key=lambda x: not x.startswith(">"))
d = {}
for k,v in groups:
# if k is False we a non match to our not x.startswith(">")
# so use the value v as the key and call next on the grouper object
# to get the next value
if not k:
key, val = list(v)[0].rstrip(), "".join(map(str.rstrip,next(groups)[1],""))
d[key] = val
print(d)
{'>Rosalind_0808': 'CCACCCTCGTGGTATGGCTAGGCATTCAGGAACCGGAGAACGCTTCAGACCAGCCCGGACTGGGAACCTGCGGGCAGTAGGTGGAAT', '>Rosalind_5959': 'CCATCGGTAGCGCATCCTTAGTCCAATTAAGTCCCTATCCAGGCGCTCCGCCGAAGGTCTATATCCATTTGTCAGCAGACACGC', '>Rosalind_6404': 'CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCCTCCCACTAATAATTCTGAGG'}
If you need order use a collections.OrderedDict in place of d.
You are looping over the length of biz. So in your last iteration biz[i+1] and biz[i+2] don't exist. There is no item after the last.

Python dictionary key error.. big mess of dictionaries in dictionaries in lists

This is kind of convoluted, so if I'm missing out on an easy construct for this, please let me know :)
I'm analysing the results of some matching experiments. At the end game, I want to be able to query things such as experiments[0]["cat"]["cat"], which yields the number of times "cat" was matched against "cat". Conversely, I could do experiments[0]["cat"]["dog"], when the first query was a cat and the match attempt was a dog.
The following is my code to populate this structure:
# initializing the first layer, a list of dictionaries.
experiments = []
for assignment in assignments:
match_sums = {}
experiments.append(match_sums)
for i in xrange(len(classes)):
for experiment in xrange(len(experiments)):
# experiments[experiment][classes[i]] should hold a dictionary,
# where the keys are the things that were matched against classes[i],
# and the value is the number of times this occurred.
experiments[experiment][classes[i]] = collections.defaultdict(dict)
# matches[experiment][i] is an integer for what the i'th match was in an experiment.
# classes[j] for some integer j is the string name of the i'th match. could be "dog" or "cat".
experiments[experiment][classes[i]][classes[matches[experiment][i]]] += 1
total_class_sums[classes[i]] = total_class_sums.get(classes[i], 0) + 1
print experiments[0]["cat"]["cat"]
exit()
So clearly this is a bit convoluted. And I'm getting a value of "1" for the last match, rather than a full dictionary at experiments[0]["cat"]. Have I approached this wrong? What could the bug here be? Sorry for the craziness and thanks for any possible help!
Two points:
Dictionary keys can be tuples; and
If you're counting things, use collections.Counter. (You can use defaultdict(int), but Counter is more useful.)
So, instead of
experiments[experiment][classes[i]][classes[matches[experiment][i]]] += 1
write
experiments = Counter()
...
experiments[experiment, classes[i], classes[matches[experiment][i]]] += 1
I just trying to guess your needs, so i tried to change order of your dimensions.
for className, classIdx in enumerate(classes):
experiment = collections.defaultdict(list)
experiments[className] = experiment
for assignment,assignmentIdx in enumerate(assignments):
counterpart = classes[matches[assignmentIdx][classIdx]]
experiment[counterpart].append((assignment,assignmentIdx))
print(len(experiments["cat"]["cat"]), len(experiments["cat"]))

Categories

Resources