比较两个包含数字的Python字符串

6 投票
5 回答
17289 浏览
提问于 2025-04-16 17:59

更新:我应该早点说明这一点,但并不是所有的名称都是简单的数字。例如,有些名称前面加了“YT”的前缀。所以像“YT1.1”这样的名称,实际上你会遇到同样的问题,比如YT1.9应该小于YT1.11。我真的很惊讶字符串比较会失败……

你好,

这个问题应该很简单,但我找不到答案。我想按名称对一堆Excel工作表进行排序。每个名称都是数字,但它们的编号方式就像教科书中的“章节”一样,意思是章节4.11在4.10之后,而4.10又在4.9和4.1之后。我以为简单地将这些数字作为字符串进行比较就可以了,但我得到了以下结果:

>>> s1 = '4.11'
>>> s2 = '4.2'
>>> s1> s2
False
>>> n1 = 4.11
>>> n2 = 4.2
>>> n1 > n2
False

我该如何比较这两个值,使得4.11大于4.2呢?

5 个回答

1

你想要的东西叫做“自然排序”。这和“字典排序”是两回事。网上有很多方法可以实现这个功能,因为你想要的具体结果可能会因实现方式不同而有所不同。快速搜索一下就能找到一些例子(注意*这不是我的代码,我也没有测试过):

import re

def tryint(s):
    try:
        return int(s)
    except:
        return s

def alphanum_key(s):
    """ Turn a string into a list of string and number chunks.
        "z23a" -> ["z", 23, "a"]
    """
    return [ tryint(c) for c in re.split('([0-9]+)', s) ]

def sort_nicely(l):
    """ Sort the given list in the way that humans expect.
    """
    l.sort(key=alphanum_key)

http://nedbatchelder.com/blog/200712.html#e20071211T054956

1

这不是一个内置的方法,但应该可以用:

>>> def lt(num1, num2):
...     for a, b in zip(num1.split('.'), num2.split('.')):
...         if int(a) < int(b):
...             return True
...         if int(a) > int(b):
...             return False
...     return False
... 
... lt('4.2', '4.11')
0: True

这个代码可以再整理一下,但大致意思就是这样。

14

将名字转换成整数的元组,然后比较这些元组:

def splittedname(s):
    return tuple(int(x) for x in s.split('.'))

splittedname(s1) > splittedname(s2)

更新: 由于你的名字可能包含数字以外的其他字符,所以你需要检查 ValueError,并且对于那些无法转换为整数的值,保持它们不变:

import re

def tryint(x):
    try:
        return int(x)
    except ValueError:
        return x

def splittedname(s):
    return tuple(tryint(x) for x in re.split('([0-9]+)', s))

要对名字列表进行排序,可以将 splittedname 作为 sorted 的关键函数:

>>> names = ['YT4.11', '4.3', 'YT4.2', '4.10', 'PT2.19', 'PT2.9']
>>> sorted(names, key=splittedname)
['4.3', '4.10', 'PT2.9', 'PT2.19', 'YT4.2', 'YT4.11']

撰写回答