忽略Python字符串中的大小写

2024-10-06 07:18:26 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中比较字符串最简单的方法是什么,忽略大小写?

当然可以(str1.lower()<;=str2.lower())等,但这会创建两个额外的临时字符串(带有明显的alloc/g-c开销)。

我想我在找一个与C的stricmp()等价的。

[需要更多的上下文,因此我将用一个简单的示例演示:]

假设您想对一个长串列表进行排序。您只需执行list.sort()。 这是O(n*log(n))字符串比较,没有内存管理(因为 字符串和列表元素是某种智能指针)。你很快乐。

现在,您也希望这样做,但是忽略这个情况(让我们简化一下 所有字符串都是ascii,因此可以忽略区域设置问题)。 您可以执行list.sort(key=lambda s:s.lower()),但随后会导致两个新的 每次比较的分配,加上重复的 (降低)弦。 每一个这样的内存管理噪声都比简单的字符串比较慢几个数量级。

现在,有了一个与stricmp()类似的函数,就可以做到:theList.sort(cmp=stricmp) 它和list.sort()一样快速,并且对内存友好。你又快乐了。

问题是任何基于Python的不区分大小写的比较都涉及隐式字符串 重复,所以我希望找到基于C的比较(可能在模块字符串中)。

找不到这样的东西,所以这里有个问题。 (希望这能澄清问题)。


Tags: 方法内存字符串lt示例列表sortlower
3条回答

作为对你澄清的回应。。。

您可以使用ctypes来执行c函数“strcasecmp”。Ctypes包含在Python2.5中。它提供了调用dll和libc等共享库的能力。下面是一个简单的示例(Linux上的Python;请参阅Win32帮助的链接):

from ctypes import *
libc = CDLL("libc.so.6")  // see link above for Win32 help
libc.strcasecmp("THIS", "this") // returns 0
libc.strcasecmp("THIS", "THAT") // returns 8

可能还想引用strcasecmp documentation

不确定这是快还是慢(还没有测试过),但这是一种使用C函数进行不区分大小写字符串比较的方法。

~~~~~~~~~~~~~~~~~~

ActiveState Code - Recipe 194371: Case Insensitive Strings 是创建不区分大小写的字符串类的配方。它可能有点过于简单,但如果您打算经常使用不区分大小写的字符串,则可以为您提供一种处理这些字符串的通用方法。

下面是一个基准测试,它表明使用^{}比接受答案建议的方法(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的版本不仅是最快的,而且也是这里所有建议的解决方案中最可移植和最易懂的。 我没有描述内存使用情况,但原始海报仍然没有给出令人信服的理由来担心它。另外,谁说对libc模块的调用不会复制任何字符串?

注意:lower()字符串方法还具有依赖于区域设置的优点。在编写自己的“优化”解决方案时,您可能会遇到一些问题。即便如此,由于Python中的错误和缺少的特性,这种比较可能会在unicode上下文中给出错误的结果。

你的问题意味着你不需要Unicode。请尝试下面的代码片段;如果它对您有效,您就完成了:

Python 2.5.2 (r252:60911, Aug 22 2008, 02:34:17)
[GCC 4.3.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.setlocale(locale.LC_COLLATE, "en_US")
'en_US'
>>> sorted("ABCabc", key=locale.strxfrm)
['a', 'A', 'b', 'B', 'c', 'C']
>>> sorted("ABCabc", cmp=locale.strcoll)
['a', 'A', 'b', 'B', 'c', 'C']

澄清:如果乍一看不明显,locale.strcoll似乎是您需要的函数,避免str.lower或locale.strxfm“重复”字符串。

相关问题 更多 >