如何进行不区分大小写的字符串比较?
如何在Python中以不区分大小写的方式比较字符串?
我想使用简单的 Python 代码封装常规字符串与存储库字符串的比较。 我还希望能够使用常规 python 字符串在由字符串散列的字典中查找值。
How can I compare strings in a case insensitive way in Python?
I would like to encapsulate comparison of a regular strings to a repository string, using simple and Pythonic code. I also would like to have ability to look up values in a dict hashed by strings using regular python strings.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
假设 ASCII 字符串:
从 Python 3.3 开始, casefold() 为更好的选择:
如果您想要一个更全面的解决方案来处理更复杂的 unicode 比较,请参阅其他答案。
Assuming ASCII strings:
As of Python 3.3, casefold() is a better alternative:
If you want a more comprehensive solution that handles more complex unicode comparisons, see other answers.
以不区分大小写的方式比较字符串似乎微不足道,但事实并非如此。 我将使用 Python 3,因为 Python 2 在这里尚未开发。
首先要注意的是,Unicode 中的大小写删除转换并非易事。 存在
text.lower() != text.upper().lower()
的文本,例如"ß"
:但是假设您想要进行无大小写比较
“BUSSE”
和“Buße”
。 哎呀,您可能还想将"BUSSE"
和"BUẞE"
进行比较 - 这是较新的大写形式。 推荐的方法是使用casefold
:不要只使用
lower
。 如果casefold
不可用,执行.upper().lower()
会有所帮助(但只是有所帮助)。那么你应该考虑口音。 如果您的字体渲染器很好,您可能会认为
"ê" == "ê"
- 但事实并非如此:这是因为后者的重音是一个组合字符。
处理这个问题最简单的方法是
unicodedata.normalize
< /a>. 您可能想使用NFKD标准化,但随意检查文档。 然后我们就完成了,这里用函数来表达:
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"ß"
: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 usecasefold
:Do not just use
lower
. Ifcasefold
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:This is because the accent on the latter is a combining character.
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 doesTo finish up, here this is expressed in functions:
使用 Python 2,在每个字符串或 Unicode 对象上调用
.lower()
... 大多数情况下都可以工作,但实际上在 @tchrist 描述的情况。
假设我们有一个名为
unicode.txt
的文件,其中包含两个字符串Σίσυφος
和ΣΊΣYΦΟΣ
。 在 Python 2 中:Σ 字符有两种小写形式:ς 和 σ,并且
.lower()
无法帮助比较它们(不区分大小写)。然而,从 Python 3 开始,所有三种形式都将解析为 ς,并且在两个字符串上调用 lower() 将正常工作:
因此,如果您关心希腊语中的三个 sigmas 等边缘情况,请使用 Python 3。
(作为参考, Python 2.7.3 和 Python 3.3.0b1 显示在上面的解释器打印输出中。)
Using Python 2, calling
.lower()
on each string or Unicode object......will work most of the time, but indeed doesn't work in the situations @tchrist has described.
Assume we have a file called
unicode.txt
containing the two stringsΣίσυφος
andΣΊΣΥΦΟΣ
. With Python 2:The Σ character has two lowercase forms, ς and σ, and
.lower()
won't help compare them case-insensitively.However, as of Python 3, all three forms will resolve to ς, and calling lower() on both strings will work correctly:
So if you care about edge-cases like the three sigmas in Greek, use Python 3.
(For reference, Python 2.7.3 and Python 3.3.0b1 are shown in the interpreter printouts above.)
Unicode 标准第 3.13 节定义了无大小写的算法
匹配。
Python 3 中的
X.casefold() == Y.casefold()
实现了“默认无大小写匹配”(D144)。大小写折叠不会在所有实例中保留字符串的规范化,因此需要进行规范化(
'å'
与'å'
)。 D145 引入了“规范无大小写匹配”:对于涉及 U+0345 字符的非常罕见的边缘情况,
NFD()
被调用两次。示例:
还有针对
'㎒'
(U+3392) 等情况的兼容性无大小写匹配 (D146) 和“标识符无大小写匹配”,以简化和优化 标识符的无大小写匹配。Section 3.13 of the Unicode standard defines algorithms for caseless
matching.
X.casefold() == Y.casefold()
in Python 3 implements the "default caseless matching" (D144).Casefolding does not preserve the normalization of strings in all instances and therefore the normalization needs to be done (
'å'
vs.'å'
). D145 introduces "canonical caseless matching":NFD()
is called twice for very infrequent edge cases involving U+0345 character.Example:
There are also compatibility caseless matching (D146) for cases such as
'㎒'
(U+3392) and "identifier caseless matching" to simplify and optimize caseless matching of identifiers.您可以使用 casefold() 方法。 casefold() 方法在比较时忽略大小写。
输出:
You can use casefold() method. The casefold() method ignores cases when comparing.
Output:
我在这里看到了这个解决方案 使用正则表达式。
它适用于重音符号
,但是不适用于不区分大小写的 unicode 字符。 谢谢@Rhymoid 指出,据我的理解,它需要确切的符号,这样案例才是真实的。 输出如下:
I saw this solution here using regex.
It works well with accents
However, it doesn't work with unicode characters case-insensitive. Thank you @Rhymoid for pointing out that as my understanding was that it needs the exact symbol, for the case to be true. The output is as follows:
通常的方法是将字符串大写或小写以进行查找和比较。 例如:
The usual approach is to uppercase the strings or lower case them for the lookups and comparisons. For example:
先转换成小写怎么样? 您可以使用
string.lower()
。How about converting to lowercase first? you can use
string.lower()
.我找到了一个干净的解决方案,我正在其中使用一些常量文件扩展名。
a clean solution that I found, where I'm working with some constant file extensions.
您可以在 str.contains() 中提及 case=False
You can mention case=False in the str.contains()
输出:
search_specicword("经济适用住房", "欧洲经济适用住房的核心")
False
search_specificword("经济适用房", "欧洲经济适用房的核心")
真的
Output:
search_specificword("Affordable housing", "to the core of affordable outHousing in europe")
False
search_specificword("Affordable housing", "to the core of affordable Housing, in europe")
True
考虑使用 FoldedCase 来自 jaraco.text:
如果您想要一个以文本为键的字典(无论大小写),请使用 FoldedCaseKeyedDict 来自 jaraco.collections:
Consider using FoldedCase from jaraco.text:
And if you want a dictionary keyed on text irrespective of case, use FoldedCaseKeyedDict from jaraco.collections:
这是另一个我在上周学会喜欢/讨厌的正则表达式,所以通常导入为(在本例中是的)反映我感受的东西!
制作一个正常的函数....要求输入,然后使用....something = re.compile(r'foo*|spam*', yes.I)...... re.I (yes.I下面)与 IGNORECASE 相同,但你不能在编写它时犯那么多错误!
然后,您使用正则表达式搜索您的消息,但老实说,这应该是它自己的几页,但重点是 foo 或垃圾邮件通过管道连接在一起,并且忽略大小写。
然后,如果找到其中一个,那么lost_n_found将显示其中一个。 如果两者都不是,则lost_n_found等于None。 如果它不等于none,则使用“returnlost_n_found.lower()”以小写形式返回user_input,
这使您可以更轻松地匹配任何区分大小写的内容。 最后(NCS)代表“没有人认真关心......!” 或者不区分大小写...
如果有人有任何问题请联系我..
This is another regex which I have learned to love/hate over the last week so usually import as (in this case yes) something that reflects how im feeling!
make a normal function.... ask for input, then use ....something = re.compile(r'foo*|spam*', yes.I)...... re.I (yes.I below) is the same as IGNORECASE but you cant make as many mistakes writing it!
You then search your message using regex's but honestly that should be a few pages in its own , but the point is that foo or spam are piped together and case is ignored.
Then if either are found then lost_n_found would display one of them. if neither then lost_n_found is equal to None. If its not equal to none return the user_input in lower case using "return lost_n_found.lower()"
This allows you to much more easily match up anything thats going to be case sensitive. Lastly (NCS) stands for "no one cares seriously...!" or not case sensitive....whichever
if anyone has any questions get me on this..