Simply call lower to make the string lowercase before calling endswith:
ext = (".dae", ".xml", ".blend", ".bvh", ".3ds", ".ase",
".obj", ".ply", ".dxf", ".ifc", ".nff", ".smd",
".vta", ".mdl", ".md2", ".md3"
".pk3", ".mdc", ".x"
".q3o", ".q3s", ".raw"
".ac", ".dxf", ".irrmesh"
".irr", ".off", ".ter"
".mdl", ".hmp", ".mesh.xml"
".skeleton.xml", ".material", ".ms3dv"
".lwo", ".lws", ".lxo"
".csm", ".cob", ".scn"
".xgl", ".zgl")
for folder, subfolders, filename in os.walk(directory):
if any([filename.lower().endswith(tuple(ext)) for filename in filenames]):
Answer from javidcf on Stack OverflowSimply call lower to make the string lowercase before calling endswith:
ext = (".dae", ".xml", ".blend", ".bvh", ".3ds", ".ase",
".obj", ".ply", ".dxf", ".ifc", ".nff", ".smd",
".vta", ".mdl", ".md2", ".md3"
".pk3", ".mdc", ".x"
".q3o", ".q3s", ".raw"
".ac", ".dxf", ".irrmesh"
".irr", ".off", ".ter"
".mdl", ".hmp", ".mesh.xml"
".skeleton.xml", ".material", ".ms3dv"
".lwo", ".lws", ".lxo"
".csm", ".cob", ".scn"
".xgl", ".zgl")
for folder, subfolders, filename in os.walk(directory):
if any([filename.lower().endswith(tuple(ext)) for filename in filenames]):
This is a really old answer but since Python 3.3, there exists the casefold() method which is more aggressive than lower() and is the more natural caseless string matching. So something like the following is an option:
filename.casefold().endswith(ext)
On a tangential note, any() short-circuits, meaning it stops at the first True, so it is much faster if any() is called on a generator expression instead of a list (especially if the matching string is towards the beginning of a long list) because with genexpr, we can stop the endswith check right away while with list, we have to perform the endswith check for every string before the any() evaluation.
So instead of
any([filename.lower().endswith(ext) for filename in filenames])
# ^ ^ <--- list
use
any(filename.lower().endswith(ext) for filename in filenames)
# ^ ^ <--- genexpr
Finally, since this question is tagged regex, here's a regex solution as well. Simply compile a pattern that ignores case and search whether the pattern matches.
import re
pat = re.compile(fr"({'|'.join(re.escape(e) for e in ext)})$", re.I)
for folder, subfolders, filenames in os.walk('.'):
if any(pat.search(filename) for filename in filenames):
# do something
What about using python's builtin str.endswith() method?
def end_other(a, b):
a_lower = a.lower()
b_lower = b.lower()
return a_lower.endswith(b_lower) or b_lower.endswith(a_lower)
I think this is what you were actually trying to do:
def end_other ( a, b ):
a = a.lower()
b = b.lower()
if a == b:
return True
elif len( a ) > len( b ):
return b == a[-len( b ):]
else:
return a == b[-len( a ):]
You had a couple of mistakes in your solution:
s1[-len(s2)]or generallys1[x]just gets a single character. So if anything, you are just comparing a single character, but not an actual sequence of characters. You splice a sequence out of a string bys[x:y](see the manual).s2[-len(s2)], even with the colon as explained above, doesn't make much sense. You are accessings2using its own length. But ass2is already the smaller string, you can compare it as a whole.- When one of your outer ifs matches a situation, there is no way any other of the outer situations can follow. For example if
ais longer thanb, there is no way thatawill be shorter or of the same length asblater on. As such you should make your if structure support that. Instead ofif ... if ... if ... elsemake a chain:if ... elif ... elif ... else. Then one automatically knows that only one of those cases can apply. - When you do that, you can also leave off the last
ifexpression. Because when neitherx < ynory < xequals to true, thenxis equal toy. - You also need to change the way you return from within the function. As of now you have a conditional exit within each of your outer if cases. Now if the first if case applies (i.e.
s1is longer thans2) and the inner if does not apply (s1does not end withs2), then you already know that the function should return False. Because there is no way that any other condition later in the code says otherwise, so you should return False immediately there (especially when there is other code that might execute later). And when you haveif x: return True else: return Falsethen you can justreturn x. s1[-len(s1)]==s2[-len(s2)]: As other as already said you will have a problem whens1ands2are empty strings.len( "" ) = 0and if both strings are empty, then both lengths are identical. And then your code tries to use an index range on an empty string, which will always fail (as there is not a single character). Instead, when you already know that two strings are of the same size, just compare both as a whole. This also helps against empty strings.
Anyway, if you didn't need to implement it on your own, you should really use str.endswith instead.
You can assert that if you start at the end of each string and match them character by character, at least one of the strings will be exhausted without any differences:
def either_endswith(a, b):
return all(a_char == b_char for a_char, b_char in zip(reversed(a), reversed(b)))
def either_endswith_case_insensitive(a, b):
return either_endswith(a.lower(), b.lower())
# Positive
either_endswith_case_insensitive('aaaa', 'a')
either_endswith_case_insensitive('a', 'aaaa')
either_endswith_case_insensitive('aaaa', 'A')
either_endswith_case_insensitive('BbbB', 'BBbb')
# Negative
either_endswith_case_insensitive('aaaa', 'c')
either_endswith_case_insensitive('a', 'ccccc')
def end_other(a, b):
if a[-len(b):].lower()==b.lower() or b[-len(a):].lower()==a.lower():
return True
return False