【问题标题】:most efficient way to look up the same index number in two different lists to compare values在两个不同列表中查找相同索引号以比较值的最有效方法
【发布时间】:2017-06-29 20:09:39
【问题描述】:

我有以下代码,这是我需要帮助的登录功能。我有两个列表 - 用户名和密码。登录功能要求用户输入用户名和密码。如果输入的用户名在用户名列表中并且对应于密码列表中的相同索引号,则返回“访问授权”,否则返回“拒绝”。

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

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

示例:

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()

注意:我知道将列表存储在二维数组中将是一个明显的解决方案/建议,但出于教学原因,此修复是必要的 - 即学生根本还没有涵盖数组。首先查看简单的解决方案,但 stackoverflow 用户也将从建议中受益,以替代/更有效的方法来解决这个问题。

更新:

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

最佳答案:

这可能是最好的答案,由 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
>>> 

【问题讨论】:

  • 你可以做一个字典,其中键,值是用户名,密码,否则if username in usernames and password in passwords:内部你需要获取密码和用户名的索引并比较它们
  • 谢谢 - 是的,字典和我在上面的编辑中提到的 2d ararys 是显而易见的建议,但目前学生只涵盖了列表,因此需要首先使用解决方案.替代解决方案也欢迎补充答案....谢谢您的建议,但我需要一个解决方案(书面),以获取密码和用户名索引的最佳编码方式。这就是我所追求的......
  • 你好小姐,我不确定我是否理解你...什么样的缩进问题?
  • 啊-如果您查看我的编辑(最后),那里的代码就是您的解决方案,但缩进问题仍然存在。它在“正确登录”语句之前产生多个“无效条目” - 我假设是因为缩进。你能解释为什么它是错误的。如果你用 user3 和 pass3 试试,你会注意到错误

标签: python list loops simultaneous


【解决方案1】:

如果你想教 Python 基础...

zip(usernames, passwords)

导致

dict(zip(usernames, passwords))

但你也可以这样做......

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

【讨论】:

  • 你能解释一下idx吗……不熟悉
  • 是变量名。
  • Enumerate 创建一个 2 元组列表,每个元组中的第一个值是数组的索引,第二个是数组中的值。然后for (idx, username) in enumerate(usernames)idx 设置为每个元素的索引,并将username 设置为每个元素的值。
  • enumerate 是一个 python 内置函数。它返回一个对象,该对象可用于在每次迭代的索引旁边迭代一个可迭代对象。
  • 修改我上面的评论:“枚举创建一个生成器......”而不是“一个列表”。
【解决方案2】:

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

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()

【讨论】:

  • 您能否在 users_pass={} 中填充一些数据,以便我们查看输入的内容和输出的内容....
  • 谢谢您,您能否在第二个答案(列表)中解释什么是“ind”......也许在该特定行上发表评论。太感谢了!我假设索引,但如果你能用一个清晰​​的解释来评论它,这将有助于学生仔细阅读这个!
  • 我想选择您的第二个答案作为答案,但缩进显示错误。在选择 user2 和 pass2 时,它会打印一个输出,在找到时重复无效的用户名和“正确的登录” - 所以不是在完全正确的地方: 输出:用户名:user2 密码:pass2 无效的用户名或密码正确的登录名无效的用户名或密码无效的用户名or password 无效的用户名或密码
  • @MissComputing 我现在添加了 cmets 和 ups,好像和你说的一样,我会更正缩进,谢谢
  • @MissComputing,缩进正确,希望能帮到你:)
【解决方案3】:

使用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 存储您唯一的用户名和密码,然后检查用户名是否在当前字典中,然后检查密码是否正确。

【讨论】:

  • 我马上看看这个。但是,为什么您说不推荐使用 zip?这对我来说很重要……!关于字典 - 你能发布解决方案吗? (尽管如前所述,学生还没有来字典,所以就我的目的而言,这不太适合目的 - 不过它可能会帮助其他人使用 stackoverflow!)
  • @MissComputing 因为在zip() 中,您需要遍历usernames and passwords 的所有对,还请注意 zip() 需要两个列表具有相同的长度,否则您将拥有一个结果不好。在字典中,您必须查看键是否存在,然后检查该值是否等于您的输入。它在字典中更有效。
  • 因此,如果有问题的列表非常庞大,则 zip 只是一个坏主意。对于绝对大小相同的相对较小的列表,建议使用 zip 吗? zip 肯定是有原因的 - 我想知道它的最佳用途是什么..
  • @MissComputing,不,zip() 不是一个坏主意。实际上 zip 是一个返回元组的生成器。运算符in 将检查元组(username, password) 是否在zip 生成的元组中。但在您目前的情况下,我建议您使用 dict 并通过它的键和值访问您的数据。
【解决方案4】:

这里还有几种方法,我都不特别推荐,但大多数其他不错的方法已在之前的答案中介绍过。

这些方法可能更适合教授一些通用的编程基础知识,但不一定适合教授 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"

【讨论】:

    【解决方案5】:

    这是zipenumerate 函数的绝佳场景。如果我没看错你的问题,你想

    • 同时遍历用户名和密码 (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! 
    

    【讨论】:

      猜你喜欢
      • 2016-05-17
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 2021-01-14
      • 2017-11-03
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多