在两个不同列表中查找相同索引号以比较值的最有效方法

most efficient way to look up the same index number in two different lists to compare values

我有以下代码,这是我需要帮助的登录功能。我有两个 列表 - 用户名和密码 。登录功能要求用户输入用户名和密码。如果输入的用户名在用户名列表中并且对应于密码列表中的相同索引号,则 return "Access granted",否则 "Denied".

出于教学目的,我会对两件事感兴趣: a) 使用指定的两个列表简单修复问题。 b) 关于解决这个问题的最佳方法的建议。 (例如字典、2darrays 或其他任何东西)。

问题是需要同时遍历两个列表并查找相同的对应索引号。

示例:

username1 和 pass1 = 已授予访问权限 但是 username1 和 pass2 =访问被拒绝

代码:

usernames=["user1","user2","user3"]
passwords=["pass1","pass2","pass3"]

def main():
   mainmenu()


def mainmenu():
   print("****MAIN MENU****")
   print("=======Press L to login :")
   print("=======Press R to register :")
   choice1=input()
   if choice1=="L" or choice1=="l":
      login()
   elif choice1=="R" or choice1=="r":
      register()
   else:
      print("please make a valid selection")

def login():
   print("*****LOGIN SCREEN******")
   username=input("Username: ")
   password=input("Password: ")
   if username in usernames and password in passwords:
      print("yes")
   else:
      print("denied")


def register():
   print("*****REGISTRATION****")
   username=input("Enter a username:")
   password=input("Enter a password:")
   usernames.append(username)
   passwords.append(password)
   answer=input("Do you want to make another registration?")
   if answer=="y":
      register()
   else:
      registration_details()

def registration_details():
   print(usernames)
   print(passwords)

main()

注意:我知道将列表存储在二维数组中是显而易见的 solution/suggestion,但出于教学原因,此修复是必要的 - 即学生还没有学习数组。首先查看简单的解决方案,但 Whosebug 用户也会从 alternate/more 解决此问题的有效方法的建议中受益。

更新:

正如有人在下面评论的那样......我想我会澄清一下。我知道需要的是获取列表中所述值的索引号。我的问题是 - 什么是最好的解决方案,或者一些解决方案。枚举。压缩。简单地使用 for 循环?很难知道如何从 python 开始,因为不只有一种方法……任何关于哪种方法最惯用 (pythonic) 的评论也会很有用。

最佳答案:

这可能是最佳答案,由 Damian Lattenero 在下方呈现 缩进,一个常见的错误,下面是关闭的。是否也可以快速评论一下原因?如何解决?

def login():
   print("*****LOGIN SCREEN******")
   username=input("Username: ")
   password=input("Password: ")
   for ind, user in enumerate(usernames):
     if username == user and passwords[ind] == password:
       print("correct login")
     else:
       print("invalid username or password")

输出

*****LOGIN SCREEN******
Username: user3
Password: pass3
invalid username or password
invalid username or password
correct login
>>> 

我建议在这种情况下使用字典,看我会告诉你如何:

users_pass = {"user1" : "pass1", "user2":"pass2", "user3":"pass3"}

def login():
   print("*****LOGIN SCREEN******")
   username=input("Username: ")
   password=input("Password: ")
   if username not in users_pass:
      print("The user doesnt exist")
   elif users_pass[username] == password:
      print("password ok")


def register():
   print("*****REGISTRATION****")
   username=input("Enter a username:")
   password=input("Enter a password:")
   users_pass[username] = password
   answer=input("Do you want to make another registration?")
   if answer=="y":
      register()
   else:
      registration_details()

如果您只想使用列表:

usernames=["user1","user2","user3"]
passwords=["pass1","pass2","pass3"]

def login():
  print("*****LOGIN SCREEN******")
  username=input("Username: ")
  password=input("Password: ")
  for index_of_current_user, current_user in enumerate(usernames): #enumerate allows to you to go throw the list and gives to you the current element, and the index of the current element
    if username == current_user and passwords[index_of_current_user] == password: #since the two list are linked, you can use the index of the user to get the password in the passwords list
      print("correct login")
    else:
      print("invalid username or password")

def register():
  print("*****REGISTRATION****")
  username=input("Enter a username:")
  password=input("Enter a password:")
  users_pass[username] = password
  answer=input("Do you want to make another registration?")
  if answer=="y":
    register()
  else:
    registration_details()

使用 zip().

可以轻松修复您的代码,但不推荐这样做

您需要替换此 if 语句:

if username in usernames and password in passwords:
    print("yes")
else:
    print("denied")

作者:

if (username, password) in zip(usernames, passwords):
    print("yes")
else:
    print("denied")

但是,您可以使用 dict 存储您唯一的用户名和密码,然后检查用户名是否在此当前字典中,然后检查密码是否正确。

如果你想教授 python 基础...

zip(usernames, passwords)

导致

dict(zip(usernames, passwords))

但你也可以...

for (idx, username) in enumerate(usernames):
   valid_password = passwords[idx]

这里还有一些方法,我不会特别推荐这两种方法,但大多数其他不错的方法已经在之前的答案中介绍了。

这些方法可能更适合教授一些通用的编程基础知识,但不一定适合教授 Python...

# Both methods assume usernames are unique

usernames=["user1","user2","user3"]
passwords=["pass1","pass2","pass3"]

username = "user2"
password = "pass2"


# Method 1, with try-catch

try:
  idx = usernames.index(username)
except ValueError:
  idx = None

if idx is not None and password == passwords[idx]:
  print "yes1"
else:
  print "denied1"


# Method 2, no try-catch

idx = None
if username in usernames:
  idx = usernames.index(username)

  if password != passwords[idx]:
    idx = None

if idx is not None:
  print "yes2"
else:
  print "denied2"

这是 zip and enumerate 函数的绝佳方案。如果我没看错你的问题,你想

  • 同时遍历用户名和密码 (zip)
  • 跟踪索引(枚举)

给定您的两个列表(用户名和密码),您需要执行以下操作

for i, (username, password) in enumerate(zip(usernames, passwords)):
    print(i, username, password)

这里是对正在发生的事情的描述。

1) zip 函数正在获取您的 usernamespasswords 列表并创建一个新列表(准确地说是一个可迭代的 zip 对象),其中每个用户名和密码都是适当的配对。

>>> zip(usernames, passwords)
<zip object at 0x_________> # hmm, cant see the contents

>>> list(zip(usernames, passwords))
[("user1", "pass1"), ("user2", "pass2"), ("user3","pass3")]

2) enumerate 函数正在获取一个列表,并创建一个新列表(实际上是一个可迭代的枚举对象),其中每个项目现在都与一个索引配对。

>>> enumerate(usernames)
<enumerate object 0x_________> # Lets make this printable

>>> list(enumerate(usernames))
[(0, "user1"), (1, "user2"), (2, "user3")]

3) 当我们结合这些时,我们得到以下结果。

>>> list(enumerate(zip(usernames, passwords))
[(0, ("user1", "pass1")), (1, ("user2", "pass2")), (2, ("user3", "pass3"))]

这为我们提供了一个列表,其中每个元素的形式为 (index, (username, password))。这是一个超级容易使用的循环!

4) 用上面的设置你的循环!

for i, (username, password) in enumerate(zip(usernames, passwords)):
    # Freely use i, username and password!