You should convert your current_users into a lowercase set and then do blazignly fast comparisons for each of your new users, just lowercased, e.g.:
current_users = ["John", "Admin", "Jack", "Ana", "Natalie"]
new_users = ["Pablo", "Donald", "Calvin", "Natalie", "Emma"]
current_users_lookup = {user.lower() for user in current_users}
for user in new_users:
if user.lower() in current_users_lookup:
print("Username {} unavailable.".format(user))
else:
print("Username {} available.".format(user))
Which would get you:
Username Pablo available. Username Donald available. Username Calvin available. Username Natalie unavailable. Username Emma available.Answer from zwer on Stack Overflow
Hi all,
I'm learning python and have been trying to figure out how to properly compare lists for case insensitivity. If I have two lists, where the first list contains the current user names and the second list is a list of new usernames, how do I get to make sure that if a new user name John won't conflict with a username in the current users of JoHn or JOHN and vice versa?
I have this so far:
current_users = ['John', 'BiLl', 'simcitizzon', 'mIke', 'cHarlie', 'admin']
new_users = ['john', 'simcitiZzon', 'ralphwiggum', 'cherrymcsperry', 'sweettooth347']
for user in new_users:
if user in current_users:
print("Sorry, " + user + " is taken.")
else:
print(user + ", this username is available")Hi everyone, I am just starting to learn how to code, running into a problem when I try to compare two lists, my code is below:
current_users = ['May', 'April', 'Wu', 'Su', 'Lulu'] new_users = ['may', 'mike', 'jones', 'chow', 'paul'] for new_user in new_users: if new_user in current_users: print('username '+new_user+' is not available.') else: print('welcome')
when I try to make the current_users list case insensitive for comparing, I used:
current_users.lower() ==['may', 'april', 'wu', 'su', 'lulu']
when I run the code, result in a violation, stated that list can not have contribute .lower().
Is there anyway to make the list case insensitive?
thanks in advance.
You should convert your current_users into a lowercase set and then do blazignly fast comparisons for each of your new users, just lowercased, e.g.:
current_users = ["John", "Admin", "Jack", "Ana", "Natalie"]
new_users = ["Pablo", "Donald", "Calvin", "Natalie", "Emma"]
current_users_lookup = {user.lower() for user in current_users}
for user in new_users:
if user.lower() in current_users_lookup:
print("Username {} unavailable.".format(user))
else:
print("Username {} available.".format(user))
Which would get you:
Username Pablo available. Username Donald available. Username Calvin available. Username Natalie unavailable. Username Emma available.
Convert everything to lowercase before doing your test:
current_users = ["John", "Admin", "Jack", "Ana", "Natalie"]
new_users = ["Pablo", "Donald", "Calvin", "Natalie", "Emma"]
current_users = [x.lower() for x in current_users]
new_users = [x.lower() for x in new_users]
If you're new to Python this is called List Comprehensions.
for username in new_users:
if username in current_users:
print("Username unavailable.")
else:
print("Username available.")
Or if the first letter of the usernames is always capitalized, you can use .title()
for username in new_users:
if username.title() in current_users:
print("Username unavailable.")
else:
print("Username available.")
Actually you can make this in just one list comprehansion:
list_A = ['Sasi', 'Babu', 'kuttappan', 'mathayi']
list_B = ['Raman', 'Kesavan', 'sasi', 'unni', 'Kuttappan', 'SaSi']
duplicated = [b for b in list_B if b.lower() in (a.lower() for a in list_A)]
print(duplicated)
This way it returns the original values while comparing the lowercased. Using sets will return the lowercased values and will delete all duplicated values in list_B.
#Might be better if we are dealing with huge lists.
list_A = ['Sasi', 'Babu', 'kuttapppan', 'mathayi']
list_B = ['Raman', 'Kesavan', 'sasi', 'unni', 'Kuttappan'].
d = [x.lower() for x in list_A] # make dict of list with less elements
for m in list_B: # search against bigger list
if m.lower() in d: print(m)
fruit.lower() in the for loop won't work as the error message implies, you can't assign to a function call..
What you could do is create an auxiliary structure (set here) that holds the lowercase items of the existing fruits in fruits, and, append to fruits if a fruit.lower() in fruit_add isn't in the t set (containing the lowercase fruits from fruits):
t = {i.lower() for i in fruits}
for fruit in fruits_add:
if fruit.lower() not in t:
fruits.append(fruit)
With fruits now being:
print(fruits)
['Apple', 'banana', 'Kiwi', 'melon', 'strawberry']
I wouldn't use the lower() function there. Use lower like this:
for fruit in fruits_add:
if fruit.lower() in fruits:
print("already in list")
Assuming ASCII strings:
string1 = 'Hello'
string2 = 'hello'
if string1.lower() == string2.lower():
print("The strings are the same (case insensitive)")
else:
print("The strings are NOT the same (case insensitive)")
As of Python 3.3, casefold() is a better alternative:
string1 = 'Hello'
string2 = 'hello'
if string1.casefold() == string2.casefold():
print("The strings are the same (case insensitive)")
else:
print("The strings are NOT the same (case insensitive)")
If you want a more comprehensive solution that handles more complex unicode comparisons, see other answers.
Comparing strings in a case insensitive way seems trivial, but it's not. I will be using Python 3, since Python 2 is underdeveloped here.
The first thing to note is that case-removing conversions in Unicode aren't trivial. There is text for which text.lower() != text.upper().lower(), such as "ß":
>>> "ß".lower()
'ß'
>>> "ß".upper().lower()
'ss'
But let's say you wanted to caselessly compare "BUSSE" and "Buße". Heck, you probably also want to compare "BUSSE" and "BUẞE" equal - that's the newer capital form. The recommended way is to use casefold:
str.casefold()
Return a casefolded copy of the string. Casefolded strings may be used for caseless matching.
Casefolding is similar to lowercasing but more aggressive because it is intended to remove all case distinctions in a string. [...]
Do not just use lower. If casefold is not available, doing .upper().lower() helps (but only somewhat).
Then you should consider accents. If your font renderer is good, you probably think "ê" == "ê" - but it doesn't:
>>> "ê" == "ê"
False
This is because the accent on the latter is a combining character.
>>> import unicodedata
>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E WITH CIRCUMFLEX']
>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']
The simplest way to deal with this is unicodedata.normalize. You probably want to use NFKD normalization, but feel free to check the documentation. Then one does
>>> unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
True
To finish up, here this is expressed in functions:
import unicodedata
def normalize_caseless(text):
return unicodedata.normalize("NFKD", text.casefold())
def caseless_equal(left, right):
return normalize_caseless(left) == normalize_caseless(right)
username = 'MICHAEL89'
if username.upper() in (name.upper() for name in USERNAMES):
...
Alternatively:
if username.upper() in map(str.upper, USERNAMES):
...
Or, yes, you can make a custom method.
str.casefold is recommended for case-insensitive string matching. @nmichaels's solution can trivially be adapted.
Use either:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
Or:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
As per the docs:
Casefolding is similar to lowercasing but more aggressive because it is intended to remove all case distinctions in a string. For example, the German lowercase letter 'ß' is equivalent to "ss". Since it is already lowercase,
lower()would do nothing to 'ß';casefold()converts it to "ss".