【问题标题】:Get sub-string for major version out of full version string从完整版本字符串中获取主要版本的子字符串
【发布时间】:2013-08-18 13:54:06
【问题描述】:

我有一个脚本,我必须在其中将完整版本的字符串转换为其主要部分。例如,我必须将1.2.3.4.5.6.7 转换为1.2

目前我正在使用这个:'.'.join(s.split('.', 2)[:-1])

>>> s = '1.2.3.4.5.6.7'
>>> '.'.join(s.split('.', 2)[:-1])
'1.2'

效果很好。但它非常丑陋,我希望有更好的方法。

编辑:

  • 性能是一个问题,因此性能不佳的答案(尽管它们可能看起来不错)对我不利。
  • '.'.join(s.split('.', 2)[:-1]) 也可以是 '.'.join(s.split('.', 2)[:2]) 一样简单

【问题讨论】:

    标签: python string split


    【解决方案1】:

    如果您预编译正则表达式,则使用正则表达式并不过分。因此

    import re
    pattern = re.compile(r'^[0-9]+\.[0-9]+')
    
    # ... later ...
    
    version = '1.2.3.4.5.6.7'
    
    def get_version(s):
        m = pattern.search(s)
        if m:
            return m.group()
    
    
    print get_version(version)
    

    这也将确保您的版本与格式匹配。

    【讨论】:

    • 任何担心性能的人请注意:这实际上比使用 OP 的 split() 方法的类似函数快了惊人的 0.01 微秒(无论如何,如果那种区别很重要,Python 是这个问题的错误语言)。
    【解决方案2】:

    使用regex

    >>> s = '1.2.3.4.5.6.7'
    >>> re.search(r'(\d+\.\d+)', s).group()
    '1.2'
    

    时序对比:

    >>> r = re.compile(r'^(\d+\.\d+)')
    
    >>> s = '100.21.3.4.5.6.7'
    >>> %timeit r.search(s).group()
    100000 loops, best of 3: 1.43 us per loop
    >>> %timeit '.'.join(s.split('.')[:2])
    1000000 loops, best of 3: 2.32 us per loop
    >>> %timeit '.'.join(s.split('.', 2)[:-1])
    100000 loops, best of 3: 1.28 us per loop
    
    >>> s = '100.21.3.4.5.6.7'*100
    >>> %timeit r.search(s).group()
    1000000 loops, best of 3: 1.96 us per loop
    >>> %timeit '.'.join(s.split('.')[:2])
    10000 loops, best of 3: 40.4 us per loop
    >>> %timeit '.'.join(s.split('.', 2)[:-1])
    100000 loops, best of 3: 2.01 us per loop
    
    >>> s = '100.21.3.4.5.6.7'*1000
    >>> %timeit r.search(s).group()
    1000000 loops, best of 3: 1.94 us per loop
    >>> %timeit '.'.join(s.split('.')[:2])
    1000 loops, best of 3: 314 us per loop
    >>> %timeit '.'.join(s.split('.', 2)[:-1])
    100000 loops, best of 3: 6.76 us per loop
    
    >>> s = '100.21.3.4.5.6.7'*10000
    >>> %timeit r.search(s).group()
    100000 loops, best of 3: 1.42 us per loop
    >>> %timeit '.'.join(s.split('.')[:2])
    100 loops, best of 3: 5.3 ms per loop        #millisecond 
    >>> %timeit '.'.join(s.split('.', 2)[:-1])
    10000 loops, best of 3: 104 us per loop
    

    基于re.findall 的解决方案也会很慢,因为它需要对整个字符串进行迭代,而re.search 在第一次匹配时停止。

    【讨论】:

    • 你的正则表达式模式有不必要的括号,因此它创建了另一个捕获组,浪费了性能。 \d 在 python 3 上也会很慢,因为默认情况下它通过 Unicode 字符类匹配字符,而不仅仅是数字 0-9
    【解决方案3】:

    另一种方式可以是'.'.join(s.split('.')[:2]),但它非常相似。我认为没有其他有效的可能性:你必须按点分割,然后只选择两个第一个元素。

    这个解决方案(或者你的,都是一样的)很好。只是避免使用正则表达式,这对于这种任务来说太过分了。

    【讨论】:

    • 其他提供正则表达式解决方案的解决方案太疯狂了。太矫枉过正了。这很好。
    • 很抱歉,您将 -1 更改为 2 并没有增加任何价值。这是相同的性能,相同的解决方案。
    • @InbarRose 我说它非常相似。没说是好是坏。为什么你要删除关于正则表达式的解释?
    • 你的答案应该是一个独立的世界,没有外部参考。因此 - 不应在网站上向其他用户发表关于他们给出的答案的评论。
    • '.'.join(s.split('.')[:2]) 甚至比 Inbar 的解决方案更糟糕,您在每个 '.' 处拆分字符串。
    【解决方案4】:

    另一种方法,寻找第二个点并将字符串切片:

    s[:s.index('.', s.index('.')+1)]
    

    It should be about as fast as the split and regex versions.

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 2021-01-31
      相关资源
      最近更新 更多