在 Python 中忽略大小写比较字符串的最简单方法是什么?
当然可以执行 (str1.lower() <= str2.lower()) 等,但这会创建两个额外的临时字符串(具有明显的 alloc/g-c 开销)。
我想我正在寻找与 C 的 stricmp() 等效的方法。
[需要更多的上下文,所以我将用一个简单的例子来演示:]
假设你想对一个很长的字符串列表进行排序。您只需执行 List.sort()。 这是 O(n * log(n)) 字符串比较并且没有内存管理(因为所有 字符串和列表元素是某种智能指针)。你很开心。
现在,您也想这样做,但忽略大小写(让我们简化并说 所有字符串都是 ascii,因此可以忽略语言环境问题)。 你可以做 theList.sort(key=lambda s: s.lower()),但是你会导致两个新的 每次比较的分配,加上重复的垃圾收集器的负担 (降低)字符串。 每个这样的内存管理噪音都比简单的字符串比较慢几个数量级。
现在,使用类似 stricmp() 的就地函数,您可以执行以下操作:theList.sort(cmp=stricmp) 它与 theList.sort() 一样快速且内存友好。你又快乐了。
问题是任何基于 Python 的不区分大小写的比较都涉及隐式字符串 重复,所以我期待找到基于 C 的比较(可能在模块字符串中)。
找不到类似的东西,因此这里的问题。 (希望这可以澄清问题)。
最佳答案
这是一个基准,显示使用 str.lower
比接受答案的建议方法(libc.strcasecmp
)更快:
#!/usr/bin/env python2.7
import random
import timeit
from ctypes import *
libc = CDLL('libc.dylib') # change to 'libc.so.6' on linux
with open('/usr/share/dict/words', 'r') as wordlist:
words = wordlist.read().splitlines()
random.shuffle(words)
print '%i words in list' % len(words)
setup = 'from __main__ import words, libc; gc.enable()'
stmts = [
('simple sort', 'sorted(words)'),
('sort with key=str.lower', 'sorted(words, key=str.lower)'),
('sort with cmp=libc.strcasecmp', 'sorted(words, cmp=libc.strcasecmp)'),
]
for (comment, stmt) in stmts:
t = timeit.Timer(stmt=stmt, setup=setup)
print '%s: %.2f msec/pass' % (comment, (1000*t.timeit(10)/10))
我机器上的典型时间:
235886 words in list
simple sort: 483.59 msec/pass
sort with key=str.lower: 1064.70 msec/pass
sort with cmp=libc.strcasecmp: 5487.86 msec/pass
因此,带有 str.lower
的版本不仅是迄今为止最快的,而且是这里提出的所有解决方案中最便携和最 Python 的。
我没有分析内存使用情况,但原始海报仍然没有给出令人信服的理由来担心它。另外,谁说对 libc 模块的调用不会复制任何字符串?
注意:lower()
字符串方法还具有依赖于语言环境的优点。在编写自己的“优化”解决方案时,您可能不会做对。即便如此,由于 Python 中的错误和缺失功能,这种比较可能会在 unicode 上下文中给出错误的结果。
关于python - 忽略 Python 字符串中的大小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62567/