Verifying the contents of list of dictionary - python

I have a list of dictionaries l1:
l1 = [
{'name':'Omer','fname':'ghaffar','sid':1},
{'name':'zoya','fname':'sattar','sid':2}
]
I'm trying to verify whether some content exists in l1. For example, I want to check if the name and sid is the same as the input values (a1 and a2), then it should display "valid user" along with the values.
My code:
a1 = input("name ")
a2 = input("sid ")
for e in l1:
if e['name'] == a1 and e['sid'] == a2:
print("valid user")
break
else:
print("invalid user")
The result I'm getting with the above code is:
name Omer
sid 1
invalid user
invalid user
I expect the result to be:
name Omer
sid 1
valid user

Change your condition to:
if e['name'] == a1 and e['sid'] == int(a2):
This is because by default input reads as string, so when you compare string with an integer, it's always a False.
Alternatively, you could also cast at the time you read from user also:
a2 = int(input("sid "))
Also note that your code keeps on printing 'invalid user' for an invalid entry or a valid entry that comes later in the list. To avoid this, you can add else to for instead of if:
a1 = input("name ")
a2 = input("sid ")
for e in l1:
if e['name'] == a1 and e['sid'] == int(a2):
print("valid user")
break
else:
print("invalid user")

Related

Python - list index out or range (unicode)

I am writing a program to encrypt / decrypt an inputted message using a key generated from a pool
The pool is created by appending unicode characters to an array
When selecting option 2 (encrypt) and reading the genkey.txt file (after generating the key with option 1), the program shows an index error as shown:
Exception has occurred: IndexError
list index out of range, line 58, in b = keyarray[a]
However, when removing the unicode script and replacing the pool with plain text (e.g [a, b, c...]) the message is encrypted without any issue.
Any way to fix this?
Code:
import random
programrun = 0
encryptedarray = []
decryptedarray = []
keyarray = []
while programrun < 1:
pool = []
for i in range(32,123): #Unicode characters
pool.append(chr(i))
print("Encryption / Decryption")
print("")
print("1. Generate Key")
print("2. Encrypt")
print("3. Decrypt")
print("4. Quit")
print("NOTE: Key must be generated before selecting Encryption / Decryption")
print("")
option = int(input("Enter the number corresponding to the option: "))
if option == 1:
a = 20
while a > 0:
b = random.randint(0,57)
c = pool[b]
keyarray.append(c)
a = a - 1
keygen = ("".join(keyarray))
print("Your generated key is:", keygen)
print("")
print("(Make sure you have generated a key before typing 'yes')")
writebool = input("Do you want to save the file to your computer? ")
if writebool == "yes":
keyfile = open("genkey.txt", "x")
keyfile.write(keygen)
keyfile.close()
wbval = 1
print("File saved to genkey.txt successfully")
print("")
quitval = 1
elif writebool == "no":
print("ok")
else:
print("Type yes or no")
elif option == 2:
encryptvalid = 0
while encryptvalid < 1:
msg = str(input("Enter the message to be encrypted: "))
genkeyf = open("genkey.txt", "r")
genkeydata = genkeyf.read()
if genkeydata == keygen:
print("File VALID")
encryptvalid = 1
for i in msg:
a = pool.index(i)
b = keyarray[a]
encryptedarray.append(b)
p = ("".join(encryptedarray))
print("")
print("Your encrypted string is: ")
print("".join(encryptedarray))
else:
print("File INVALID")
print("Please check if the genkey.txt file matches the current generated key.")
a = pool.index(i) looks up the index of a character of the message in the pool, then that index is used to lookup a value in the keyarray with b = keyarray[a].
pool is 91 bytes long, but keyarray is 20 bytes long, so many of the indexes are too high. You probably want b = keyarray[a % len(keyarray)]. This uses the modulus operator to constrain the lookup from 0-19.

Why IF statement become false , If I write a name present in the nested list

When I input "Ali" it jumps to new user statement. Anyone please explain me why?
Data_base = [["Ali","1234","5000"],["Sara","1234","2000"]]
User_name = input("Enter your name")
if User_name in Data_base:
print("User persent")
elif User_name not in Data_base:
print("New User")
New_User_name = input("Your name: ")
Data_base.append(New_User_name)
print(Data_base)
The problem is that your list is made up of two separate lists.
Data_base = [["Ali","1234","5000"],["Sara","1234","2000"]]
So when you check if the input is in the list, Python checks if any of the internal values are equal to the input. i.e.:
input = ["Ali","1234","5000"] or input = ["Sara","1234","2000"]
By grouping it into a list I assume the second and third values belong to the first value. Instead of the list I would suggest using a dictionary:
Data_base = {"Ali" : ["1234","5000"], "Sara" : ["1234","2000"]}
And then, for checking:
if User_name in Data_base:
print("User persent")
else:
# Do whatever

UnboundLocalError: local variable 'a1' referenced before assignment

def para(value):
if(value==1):
a1=10
b1=11
c1=12
d1=13
elif(value==2):
a1=20
b1=21
c1=22
d1=23
elif(value==3):
a1=30
b1=31
c1=32
d1=33
else:
print("wrong input")
dict_a=dict({'a':a1,'b':b1})
dict_b=dict({'c':c1,'d':d1})
return(dict_a, dict_b)
def main():
global dict_a, dict_b
value=input("enter the choice: \n1. 1st \n2. 2nd \n3. 3rd \n4. 4th")
[dict_a, dict_b]=para(value)
main()
The error that I get is:
dict_a=dict({'a':a,'b':b})
UnboundLocalError: local variable 'a1' referenced before assignment
If your code hits the else block, a1 won't be assigned a value.
You can fix this in one of the following two ways:
Assign a default value in case it doesn't get assigned in the conditional blocks.
a1 = 0
b1 = 0
c1 = 0
d1 = 0
if(value==1):
a1=10
b1=11
c1=12
d1=13
elif(value==2):
a1=20
b1=21
c1=22
d1=23
elif(value==3):
a1=30
b1=31
c1=32
d1=33
else:
print("wrong input")
Or assign the variables in the else block which will achieve basically the same thing
if(value==1):
a1=10
b1=11
c1=12
d1=13
elif(value==2):
a1=20
b1=21
c1=22
d1=23
elif(value==3):
a1=30
b1=31
c1=32
d1=33
else:
a1 = 0
b1 = 0
c1 = 0
d1 = 0
print("wrong input")
If you don't want the user to use these default values, you can always throw an exception in the else that lets the user know they've inputted the wrong values
You should rather initialise the dictionary only in case of valid input
def para(value):
dict_a = dict()
dict_b = dict()
if(value==1):
dict_a={'a':10,'b':11}
dict_b={'c':12,'d':13}
elif(value==2):
dict_a={'a':20,'b':21}
dict_b={'c':22,'d':23}
elif(value==3):
dict_a={'a':30,'b':31}
dict_b={'c':32,'d':33}
else:
print("wrong input")
return(dict_a, dict_b)

Look up salary information by name from a list

I'm writing some python code that works out a person's total pay.
I am able to do this by getting the user to input their pay, however I would like them just to be able to enter their name and then the name is searched in position 0 of a list (Eg. 0,1 0,2 0,2 etc).
I have tried using a tuple but it is not callable and the dictionary and list would not work for me either.
counter = 0
valid = 0
employeelist = [["thomas","2","500"], ["jake","1","750"]]
while True:
while True:
try:
name = str(input("Name:"))
except ValueError:
print("Error")
continue
else:
break
while True:
if name == employeelist[counter,0]:
print(employeelist[counter])
break
valid = 1
elif counter = 3:
print("invalid name")
break
else:
counter = counter + 1
if valid == 1:
break
months = employeelist[counter,1]
pay = employeelist[counter,1]
totalpay = int(months) * int(pay)
Edit:
I do no longer have the code with the dictionary, however I just edited the code from [counter,1] and [0,1] to [counter][1] and is working fine thank you :D
The code below is for your inner loop
employeelist = [["thomas","2","500"], ["jake","1","750"]]
name = ""
while True:
try:
name = input("Name:")
break
except:
print "Error"
position = -1
for i, element in enumerate(employeelist):
if element[0] == name:
position = i
break
if position == -1:
print "Invalid Name"
else:
totalpay = int(employeelist[position][1]) * int(employeelist[position][2])
Your code have multiple bugs. First, valid=1, is set after breaking the loop -meaning valid=1,is never set. You also are checking elif counter = 3 this way, you should rather use two equality signs, like this: elif counter == 3
The error you are getting, that list indices must be integers or slices, not tuple, you are having because you are accessing a multidimensional array the wrong way. Instead of name == employeelist[counter, 0], it should be name == employeelist[counter][0].
Your way of iterating through the array is possible, but its rather simpler using a for loop.
Try this way.
for employees in employeelist:
if name == employees[0]:
print(employee)
valid = 1
break
If it iterated through the hole employeelist, without the if-block running, valid = 1, would never been set.
Working code:
counter = 0
valid = 0
employeelist = [["thomas","2","500"], ["jake","1","750"]]
while True:
while True:
try:
name = str(input("Name: "))
except ValueError:
print("Error")
continue
else:
break
for employees in employeelist:
if name == employees[0]:
print(employees)
valid = 1
break
if valid == 1:
break
months = employeelist[counter][1]
pay = employeelist[counter][2]
totalpay = int(months) * int(pay)
print(totalpay)

Dictionary true/false error

i'm trying to allow the user to change the value for a dictionary, my dictionary is d as follows:
d = {'gary:' : 'B','john:': 'C',}
Whenever I type in 'gary:'(gary with a semicolon) for the nameedit input, the why variable will always result in true but regardless, it will read the value as none and never reach the second input for the letter grade(inpu)
nameedit = str(input("Which student do you wish to edit the grade of?"))
why = print(nameedit in d)
if why == None:
print("That student doesn't exist")
else:
inpu = str(input("Enter new letter grade: A,B,C,D,F,"))
d[nameedit] = inpu
print(d)
I also tried some variations on this such as if nameedit == True: and an else with the same problem, the print statement will yield True but it will just continue to the else statement. I also tried a elif nameedit in d:
why = print(nameedit in d)
if nameedit in d == True:
inpu = str(input("Enter new letter grade: A,B,C,D,F,"))
d[nameedit] = inpu
print(d)
else:
print("That student doesn't exist")
, but with no avail. Is it impossible to pick up the value the print statement is reading? My ultimate goal is to simply check if the name is in the dictionary, if it is, continue, if it isn't, stop
python v 3.5
Use:
why = nameedit in d
if why:
inpu = str(input("Enter new letter grade: A,B,C,D,F,"))
d[nameedit] = inpu
print(d)
else:
print('Does not exists')
print() just puts output to the screen; it does not return what it is printing. If you want to assign why to the result of nameedit in d and print it; do it on separate lines:
why = nameedit in d
print(why)
Also, if ... is seeing if ... is True. Using if ... == True is seeing if ... == True == True. That is redundant. Just do this:
why = nameedit in d
print(why)
if why:
inpu = input("Enter new letter grade: A,B,C,D,F,")
d[nameedit] = inpu
print(d)
else:
print("That student doesn't exist")
I also removed your conversion of input(...) to a string. It already returns a string, so the conversion is redundant.
nameedit in d returns True or False, never None. And wrapping in print (which always returns None) is just nonsensical.
Remove the print wrapping, and change the test to if not why: or just move the test into the condition itself:
nameedit = input("Which student do you wish to edit the grade of?")
if nameedit not in d:
print("That student doesn't exist")
else:
d[nameedit] = input("Enter new letter grade: A,B,C,D,F,")
print(d)
I removed unnecessary str wrapping (input already returns str in Py3), and unnecessary intermediate locals.
Use just like:
if why in d:
or
if why not in d:
You don't need use two strings for this. Also, you can get value with get:
d = {'gary:' : 'B','john:': 'C',}
name = str(input("Which student do you wish to edit the grade of?\n"))
value = d.get(name, None)
if not value:
print("That student doesn't exist: {0}: [1}".format(name, value))
else:
value = str(input("Enter new letter grade: A,B,C,D,F \n"))
d[name] = value.upper()
print(d)

Categories