How to see if a list is within another list
Question:
I am making a simple program to return True/False if the login details supplied by the user match the details in a list.
...
details = [['Charlie', 'Password'],
['Turnbull', 'Password']]
def authenticate():
login_details = get_entry_values() # list of user input [username, password]
for username, password in details:
if login_details[0] == username and login_details[1] == password:
print("Authenticated")
return True
else:
print("Incorrect")
return False
However when I enter the first login details (‘Charlie’ followed by ‘Password’) it returns True but when I enter the second it returns False
Answers:
Since you have a list of lists, and you want to see whether a given list is in the list of lists, you don’t need to loop over the list. You can just do:
def authenticate():
login_details = get_entry_values()
if login_details in details:
print("Authenticated")
return True
else:
print("Incorrect")
return False
If you don’t want to print anything (which you probably shouldn’t, as this makes code reuse harder) then the function can be reduced to:
def authenticate():
return get_entry_values() in details
However, let’s go back to your original code and see what the problem is with it. It’s simple: you only ever check the first password in the list. Your if
statement always returns, whether there was a match or not, and so the code never considers the second or subsequent items in details
. What you need to do is keep checking if you don’t get a match. In other words, the password cannot be declared incorrect until you have finished the loop. So:
def authenticate():
login_details = get_entry_values() # list of user input [username, password]
for username, password in details:
if login_details[0] == username and login_details[1] == password:
print("Authenticated")
return True
print("Incorrect")
return False
As others have noted in comments, a dictionary is a better data structure for storing user names and passwords. If you used a dictionary, you wouldn’t need a loop at all:
details = {'Charlie': 'Password',
'Turnbull': 'Password'}
def authenticate():
username, password = get_entry_values()
authenticated = details.get(username) == password
print("Authenticated" if authenticated else "Incorrect")
return authenticated
The use of dict.get()
here returns None
if the username isn’t in the dictionary, and None
is never equal to any string, so this is effectively checking both that the username exists and that the password is correct at the same time.
I am making a simple program to return True/False if the login details supplied by the user match the details in a list.
...
details = [['Charlie', 'Password'],
['Turnbull', 'Password']]
def authenticate():
login_details = get_entry_values() # list of user input [username, password]
for username, password in details:
if login_details[0] == username and login_details[1] == password:
print("Authenticated")
return True
else:
print("Incorrect")
return False
However when I enter the first login details (‘Charlie’ followed by ‘Password’) it returns True but when I enter the second it returns False
Since you have a list of lists, and you want to see whether a given list is in the list of lists, you don’t need to loop over the list. You can just do:
def authenticate():
login_details = get_entry_values()
if login_details in details:
print("Authenticated")
return True
else:
print("Incorrect")
return False
If you don’t want to print anything (which you probably shouldn’t, as this makes code reuse harder) then the function can be reduced to:
def authenticate():
return get_entry_values() in details
However, let’s go back to your original code and see what the problem is with it. It’s simple: you only ever check the first password in the list. Your if
statement always returns, whether there was a match or not, and so the code never considers the second or subsequent items in details
. What you need to do is keep checking if you don’t get a match. In other words, the password cannot be declared incorrect until you have finished the loop. So:
def authenticate():
login_details = get_entry_values() # list of user input [username, password]
for username, password in details:
if login_details[0] == username and login_details[1] == password:
print("Authenticated")
return True
print("Incorrect")
return False
As others have noted in comments, a dictionary is a better data structure for storing user names and passwords. If you used a dictionary, you wouldn’t need a loop at all:
details = {'Charlie': 'Password',
'Turnbull': 'Password'}
def authenticate():
username, password = get_entry_values()
authenticated = details.get(username) == password
print("Authenticated" if authenticated else "Incorrect")
return authenticated
The use of dict.get()
here returns None
if the username isn’t in the dictionary, and None
is never equal to any string, so this is effectively checking both that the username exists and that the password is correct at the same time.