1

Pretty much a Python newbie here and trying to learn. I have a script that a colleague started and I'm working on adding new functionality to it. I'd like to validate that a user input is within one of two lists I have.

I have a raw input from the user asking for a site name and I'd like to add code that will check if the user's input is within the pre-defined lists sites_2017 and sites_2018 (which are used later in the code), then return an error if it isn't or proceed with the rest of the script if it is. I've been searching around and have seen lots of different while loop answers as well as functions, but none so far that reference multiple lists to match against.

Just trying to wrap my head around this and figure out the best code for it as well as where in the current code a while loop, etc would need to go.

# Ask user input for what they'd like to do? Render or audit? _Step user through process_

import os
import subprocess

getuser = raw_input("Please enter your username :")

print("1. render_device")
print("2. audit_deivce")
askuser = raw_input("Would you like to render_device or audit_deivce? : ")

#Render:

if askuser == "1":
        get_site_name = raw_input("Please enter the site name you'd like to render :")

        sites_2017 = ["bob", "joe", "charlie"]
        sites_2018 = ["sarah", "kelly", "christine"]
martineau
  • 119,623
  • 25
  • 170
  • 301
mistertim
  • 9
  • 3

2 Answers2

1

Updated to address comments

You will want to leverage in here and it's best to create a set from the two lists as mentioned by @abarnert in the comments. You could wrap this inside of a function and recursively call the function if the conditions are not satisfied (note I have changed raw_input() to input() for Python 3 compatibility):

getuser = input("Please enter your username :")

print("1. render_device")
print("2. audit_device")

askuser = input("Would you like to render_device or audit_device? : ")

def verify_input(sites_set):

    get_site_name = input("Please enter the site name you'd like to render :")

    if get_site_name in sites_set:
        print('Proceed')
        return
    else:
        print('Not in either list!')
        verify_input(sites_set)

if askuser == "1":

        sites_2017 = ["bob", "joe", "charlie"]
        sites_2018 = ["sarah", "kelly", "christine"]

        verify_input(set(sites_2017 + sites_2018))

EDIT

However, a much simpler implementation is to just use a while loop:

getuser = input("Please enter your username :")

print("1. render_device")
print("2. audit_device")

askuser = input("Would you like to render_device or audit_device? : ")

if askuser == "1":

        sites_2017 = ["bob", "joe", "charlie"]
        sites_2018 = ["sarah", "kelly", "christine"]

        sites_set = set(sites_2017 + sites_2018)
        proceed = False

        while not proceed:

            get_site_name = input("Please enter the site name you'd like to render :")

            if get_site_name in sites_set:
                print('Proceed')
                proceed = True
            else:
                print('Not in either list!')
rahlf23
  • 8,869
  • 4
  • 24
  • 54
  • There's no need for a comprehension if you combine the lists instead: `if get_site_name in sites_2017 + sites_2018:` – nicholishen Aug 20 '18 at 21:06
  • Thanks! Looks like this works pretty well, though when it encounters an input that isn't in either of the lists it simply goes on to the next part of the script regardless. How would I have it request the get_site_name input again until it gets a name matching one of the lists? – mistertim Aug 20 '18 at 21:19
  • If the lists are big enough that concatenating them together is a problem, they're big enough that linear-searching all of them (even with short-circuiting) is a problem, so you really to pull them out of any inner loop and make a set out of all values in all lists and then just do `in sites_set`. – abarnert Aug 20 '18 at 21:21
  • @rahlf23 I didn't say "list", I said comprehension. It is a generator comprehension and you are creating a list of lists which is the same overhead as combining two lists. Also, it is not easier to add a list to a list-of-lists than the method I proposed. Finally, `any` doesn't offer any optimization when comparing the two methods. – nicholishen Aug 20 '18 at 21:25
  • I've updated my answer to address the series of comments / suggestions here. – rahlf23 Aug 20 '18 at 21:47
  • That's unnecessary overhead. O(n) to hash all items in the list + O(1) to check membership. It's only ever going to be called once during runtime after initialization. `if site_name in sites1 + sites2:` is still more efficient and simpler. PEP20: "Simple is better than complex" – nicholishen Aug 20 '18 at 23:25
  • Why are you using recursion instead of a simple `while` loop? – PM 2Ring Aug 22 '18 at 16:04
  • @PM2Ring good point. Edited to include solution with while loop. – rahlf23 Aug 22 '18 at 16:10
0

In python you can use the membership testing operator in. So instead of checking using loops you can combine your lists and check membership like so:

if get_site_name in sites_2017 + sites_2018:
nicholishen
  • 2,602
  • 2
  • 9
  • 13