【问题标题】:Python how to force one string to match format of anotherPython如何强制一个字符串匹配另一个字符串的格式
【发布时间】:2013-08-07 22:14:47
【问题描述】:

我为我工作的评估员办公室编写了一些 Python 脚本。其中大多数要求输入包裹 ID 号(然后用于通过 odbc 获取某些数据)。他们在输入包裹 ID 的方式上并不一致。

所以这是我的问题,他们以 3 种方式之一输入包裹 ID:

1: '1005191000060'

2: '001005191000060'

3: '0010-05-19-100-006-0'

第三种方式是正确的方式,所以我需要确保输入是固定的以始终匹配该格式。当然,他们宁愿使用前两种方式之一输入 ID。包裹号码必须始终为 15 位数字(20 位带破折号)

我目前有一个关于如何修复包裹 ID 的工作方法,但它非常难看。我想知道是否有人知道更好的方法(或更“Pythonic”的方法)。我有一个通常会导入所有这些脚本的函数。这是我所拥有的:

import re

def FormatPID(in_pid):
    pid_format = re.compile('\d{4}-\d{2}-\d{2}-\d{3}-\d{3}-\d{1}')
    pid = in_pid.zfill(15) 
    if not pid_format.match(pid):
        fixed_pid = '-'.join([pid[:4],pid[4:6],pid[6:8],pid[8:11],pid[11:-1],pid[-1]])
        return fixed_pid
    else:
        return pid

if __name__ == '__main__':

    pid = '1005191000060'
##    pid = '001005191000060'
##    pid = '0010-05-19-100-006-0'

    # test
    t = FormatPID(pid)
    print t

这确实工作得很好,但是我已经被这个丑陋的代码困扰了一段时间,我认为必须有比切片更好的方法。我希望有一种方法可以“强制”将其转换为字符串以匹配“pid_format”变量。有任何想法吗?我在正则表达式模块中找不到任何可以做到这一点的东西

【问题讨论】:

    标签: python regex string python-2.7 formatting


    【解决方案1】:

    我不会费心使用正则表达式。您只想获取所有数字,忽略连字符,用 0 左填充,然后在正确的位置插入连字符,对吗?所以:

    def format_pid(pid):
        p = pid.replace('-', '')
        if not p.isdigit():
            raise ValueError('Invalid format: {}'.format(pid))
        p = p.zfill(15)
        # You can use your `join` call instead of the following if you prefer.
        # Or Ashwini's islice call.
        return '{}-{}-{}-{}-{}-{}'.format(p[:4], p[4:6], p[6:8], p[8:11], p[11:14], p[14:])
    

    【讨论】:

    • 我不认为(s)他想做任何填充,(s)他希望他们输入确切的数字,然后将破折号插入适当的位置。
    • @EricAmorde:如果他不想做任何填充,那么示例 #1 将如何工作?
    • 感谢 abarnert。我想我会坚持埃里克的回答。我想摆脱“丑陋的切片”。这和我原来的帖子没什么不同。虽然,我确实喜欢你对 isdigit() 的使用,而不是我的正则表达式。我对“\d”的使用不会做同样的事情吗?文档说:
    • \d 未指定 UNICODE 标志时,匹配任何十进制数字;这等效于集合 [0-9]。使用 UNICODE,它将匹配 Unicode 字符属性数据库中分类为十进制数字的任何内容。
    • @cmackey: 好吧,isdigit() 会做同样的事情,因为正则表达式被明确地设计成与isdigit() 相同的意思。它只会更简单、更快,而且更难出错。但是请注意,您的代码假设您将所有连字符都放在了正确的位置,或者您除了数字之外什么都没有;我的代码正在检查您是否只有数字或连字符,忽略连字符并使用数字。
    【解决方案2】:

    你可以使用itertools.islice代替手动切片:

    import re
    from itertools import islice
    groups = (4, 2, 2, 3, 3, 1)
    def FormatPID(in_pid):
        pid_format = re.compile('\d{4}-\d{2}-\d{2}-\d{3}-\d{3}-\d{1}')
        in_pid = in_pid.zfill(15)
        if not pid_format.match(in_pid):
            it = iter(in_pid)
            return '-'.join(''.join(islice(it, i)) for i in groups)
        return in_pid
    
    print FormatPID('1005191000060')
    print FormatPID('001005191000060')
    print FormatPID('0010-05-19-100-006-0')
    

    输出:

    0010-05-19-100-006-0
    0010-05-19-100-006-0
    0010-05-19-100-006-0
    

    【讨论】:

    • 可爱...我试图找到一些类似的东西。我只是讨厌看着我正在做的丑陋的切片操作。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多