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

Asked By: Charlie

||

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.

Answered By: kindall
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.