如何比较字符串?
- 2024-11-26 08:36:00
- admin 原创
- 189
问题描述:
我想知道 Python 如何进行字符串比较,更具体地说,当使用小于<
或大于运算符时它如何确定结果。>
例如,如果我输入,print('abc' < 'bac')
我会得到True
。我知道它比较字符串中的相应字符,但是不清楚为什么由于缺乏更好的术语,将更多的“权重”放在第一个字符串中a
小于(第一个位置)的事实上,而不是放在第二个字符串中小于(第二个位置)b
的事实上。a
`b`
当字符串包含数字表示并希望通过数值比较数字时,许多人会问这个问题。直接的解决方案是先转换值。请参阅如何将字符串解析为浮点数或整数?。如果列表或其他集合中有多个数字,请参阅如何在列表、字典等中收集重复计算的结果(或复制每个元素均已修改的列表)?进行批量转换。
如果您尝试比较包含数字序列的字符串,将数字视为数字(有时称为“自然排序”),请参阅是否有用于字符串自然排序的内置函数?。
解决方案 1:
来自文档:
比较使用字典顺序:首先比较前两个项目,如果它们不同,则确定比较的结果;如果它们相等,则比较接下来的两个项目,依此类推,直到任一序列都用尽。
还:
字符串的词典顺序使用 Unicode 代码点编号来对单个字符进行排序。
或者在Python 2上:
字符串的词典顺序使用单个字符的 ASCII 顺序。
举个例子:
>>> 'abc' > 'bac'
False
>>> ord('a'), ord('b')
(97, 98)
False
一旦a
发现小于,则立即返回结果b
。 不再比较其他项(如第二项所示:b
>a
为True
)。
注意大小写:
>>> [(x, ord(x)) for x in abc]
[('a', 97), ('b', 98), ('c', 99), ('d', 100), ('e', 101), ('f', 102), ('g', 103), ('h', 104), ('i', 105), ('j', 106), ('k', 107), ('l', 108), ('m', 109), ('n', 110), ('o', 111), ('p', 112), ('q', 113), ('r', 114), ('s', 115), ('t', 116), ('u', 117), ('v', 118), ('w', 119), ('x', 120), ('y', 121), ('z', 122)]
>>> [(x, ord(x)) for x in abc.upper()]
[('A', 65), ('B', 66), ('C', 67), ('D', 68), ('E', 69), ('F', 70), ('G', 71), ('H', 72), ('I', 73), ('J', 74), ('K', 75), ('L', 76), ('M', 77), ('N', 78), ('O', 79), ('P', 80), ('Q', 81), ('R', 82), ('S', 83), ('T', 84), ('U', 85), ('V', 86), ('W', 87), ('X', 88), ('Y', 89), ('Z', 90)]
具体来说,这会导致、等(包括所有)的计算结果'a' > 'A'
为'b' > 'B'
,'a' > 'Z'
因为True
从 a 到 z 的所有小写字符都比所有大写字符具有更高的代码点编号。
解决方案 2:
Python 字符串比较是按字典顺序进行的:
来自 Python 文档:http ://docs.python.org/reference/expressions.html
字符串按其字符的数值等价物(内置函数 ord() 的结果)按字典顺序进行比较。在此行为中,Unicode 和 8 位字符串完全可互操作。
因此,在您的示例中'abc' < 'bac'
,'a' 在数值上(在 ASCII 和 Unicode 表示中)位于 'b' 之前(小于),所以比较就此结束。
解决方案 3:
Python 以及几乎所有其他计算机语言都使用与您在印刷词典中查找单词时使用的相同原则(我希望):
(1)根据所涉及的人类语言,你有一个字符排序的概念:'a'<'b'<'c'等
(2)第一个字符比第二个字符更重要:'az' < 'za'(无论语言是从左到右书写还是从右到左书写还是牛耕式书写都无关紧要)
(3)如果没有字符需要测试,较短的字符串将小于较长的字符串:'foo' < 'food'
通常,在计算机语言中,“字符排序的概念”相当原始:每个字符都有一个与人类语言无关的数字ord(character)
,并使用该数字对字符进行比较和排序。通常,这种排序并不适合用户的人类语言,然后您需要进入“排序”,这是一个有趣的话题。
解决方案 4:
另请参阅如何在 Python 中按字母顺序对 Unicode 字符串进行排序?其中讨论了 Unicode 排序算法 ( http://www.unicode.org/reports/tr10/ ) 给出的排序规则。
回复评论
什么?除了从左到右,还能如何定义排序?
根据 S.Lott 的说法,在对法语进行排序时有一个著名的反例。它涉及重音:实际上,可以说,在法语中,字母是从左到右排序的,而重音是从右到左排序的。下面是反例:我们有 e < é 和 o < ô,因此您会期望单词 cote、coté、côte、côté 的排序为 cote < coté < côte < côté。然而,事实并非如此,事实上您有:cote < côte < coté < côté,即,如果我们删除“c”和“t”,我们会得到 oe < ôe < oé < ôé,这正是从右到左的排序。
最后一点:您不应该谈论从左到右和从右到左的排序,而应该谈论正向和反向排序。
确实有一些语言是从右到左书写的,如果你认为阿拉伯语和希伯来语是从右到左排序的,那么从图形的角度来看你可能是对的,但从逻辑层面来看你是错的!
事实上,Unicode 认为字符串是按逻辑顺序编码的,而书写方向是字形层面上发生的现象。换句话说,即使在单词 שלום 中,字母 shin 出现在 lamed 的右侧,但从逻辑上讲,它出现在 lamed之前。要对这个单词进行排序,首先要考虑 shin,然后是 lamed,然后是 vav,然后是 mem,这是正向排序(尽管希伯来语是从右到左书写的),而法语重音符号则反向排序(尽管法语是从左到右书写的)。
解决方案 5:
这是字典顺序。它只是将事物按字典顺序排列。
解决方案 6:
纯 Python 的字符串比较等效于:
def less(string1, string2):
# Compare character by character
for idx in range(min(len(string1), len(string2))):
# Get the "value" of the character
ordinal1, ordinal2 = ord(string1[idx]), ord(string2[idx])
# If the "value" is identical check the next characters
if ordinal1 == ordinal2:
continue
# It's not equal so we're finished at this index and can evaluate which is smaller.
else:
return ordinal1 < ordinal2
# We're out of characters and all were equal, so the result depends on the length
# of the strings.
return len(string1) < len(string2)
此函数的作用相当于实际方法(Python 3.6和Python 2.7),只是速度慢得多。另请注意,该实现并不完全符合“Python 风格”,仅适用于<
比较。它只是为了说明其工作原理。我还没有检查它是否像 Python 的组合 Unicode 字符比较一样工作。
更通用的变体是:
from operator import lt, gt
def compare(string1, string2, less=True):
op = lt if less else gt
for char1, char2 in zip(string1, string2):
ordinal1, ordinal2 = ord(char1), ord(char2)
if ordinal1 == ordinal2:
continue
else:
return op(ordinal1, ordinal2)
return op(len(string1), len(string2))
解决方案 7:
字符串按其字符的数值等价物(内置函数 ord() 的结果)按字典顺序进行比较。在此行为中,Unicode 和 8 位字符串完全可互操作。