String
String

Reputation: 165

Check, using a list, if a string contains a certain letter or number

The question I'm answering requires you to validate a Car Reg Plate. It must look for a sequence of two letters, then three numbers, then three letters, otherwise return a message like "not a valid postcode"

I need to know how to check if a string contains a certain letter, or number, by comparing it with a list.

So far, I've got this:

# Task 2

import random
import re

def regNumber():
    # Generate a Car Reg Number
    letters = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    numbers = ["1","2","3","4","5","6","7","8","9","0"]

    letter1 = random.choice(letters)
    letter2 = random.choice(letters)
    number1 = random.choice(numbers)
    number2 = random.choice(numbers)
    letter3 = random.choice(letters)
    letter4 = random.choice(letters)
    letter5 = random.choice(letters)
    licensePlate = (letter1 + letter2 + number1 + number2 + letter3 + letter4 + letter5)
    return licensePlate, letters, numbers

carReg, letters, numbers = regNumber()

print(carReg)
if letters not in carReg: print("Success")

However, I get this error:

TypeError: 'in <string>' requires string as left operand, not list

Any help appreciated.

Upvotes: 1

Views: 4456

Answers (5)

wwii
wwii

Reputation: 23743

You could do it without regular expressions:

Define the pattern you want using str methods in a list

pattern = [str.isalpha, str.isalpha,
           str.isdigit,  str.isdigit,  str.isdigit,
           str.isalpha, str.isalpha, str.isalpha]

Use that pattern to check a string.

def is_foo(pattern, s):
    '''Return True if s matches pattern

    s is a string
    pattern is a list of functions that return a boolean
    len(s) == len(pattern)
    each function in pattern is applied to the corresponding character in s
    '''
    # assert len(s) == len(pattern)
    return all(f(c) for f, c in zip(pattern, s))

Usage

if is_foo(pattern, 'aa111aaa'):
    print 'yes!!!'

if not is_foo(pattern, '11aa111'):
       print ':('

Upvotes: 0

change

if letters not in carReg: print("Success")

to

for l in letters:
    if l not in carReg: 
        print("Success")

in your code you are having a list of strings and, that is why I have changed your if condition to a for loop so that each element of the list is checked for occurance in carReg string.

alternatively, i think you should be using a flag to solve your probem. Like so:

flag = 0
for l in letters:
    if l in carReg: 
        flag = 1
        break

if flag == 0:
    print("Success")

Upvotes: 1

TooLateTheHero
TooLateTheHero

Reputation: 55

Another way in which you could generate a certain number of letters rather than having to use so many variables would be to use just two variables that would allow the generation of, for the first one, 2 letters and for the second 3 letters. An example of how I would implement this would be:

def randomLetters1(y):
    return ''.join(random.choice(string.ascii_uppercase) for x in range(y))
firstLetters = (randomLetters1(2))
secondLetters = (randomLetters1(3))

I know this because I have had to do this exact same task.

Upvotes: 0

dm03514
dm03514

Reputation: 55952

The error is telling you the exact issue in this case,

letters is a list being returend from regNumber but in requires a string on the leftside

like 'ASD111' in carReg

Upvotes: 1

HavelTheGreat
HavelTheGreat

Reputation: 3386

You need to be checking for characters in your string with this method, it will not simply iterate over your list for you.

Try using something like this instead, to check every character in your list of strings:

if any(letter in carReg for letter in letters):

This will cut out on the first True, which is I think what you're looking for.

Note: If using any like this is unfamiliar territory for you, you can also always just iterate over every string within your list of strings to check for those given characters.

Update: If you're attempting to match a given format of letters and numbers, it would make much more sense (IMHO) for you to familiarize yourself with Python's regex methods to pattern match to a valid license plate than attempt to use loops to validate one. I won't write the regex for your particular case, but to give you an idea, the following would allow you to match 3 letters followed by 1-4 digits (valid license plate where I live)

match_plate = re.compile(r"^[A-Z]{3}\d{1,4}$",re.I)

If you really must use a list to check, you will have to use a series of conditional statements to split the license plate into parts over which you can validate with iterations.

Upvotes: 5

Related Questions