在某个字符后从字符串中提取数字

时间:2016-09-14 02:53:01

标签: python

Ayyyy,我需要一些帮助。我有以下字符串,总是以“char,num”格式:

s = "abcdef,12"
v = "gbhjjj,699"

我想得到逗号后的数字,如何在不将逗号分隔字符串作为分隔符的情况下执行此操作?

我尝试了s[-2:]v[-3:],但是如何在不知道位数的情况下让它工作?

5 个答案:

答案 0 :(得分:2)

假设:

  • 知道字符串中有逗号,因此您无需搜索整个字符串以查明是否存在。
  • 你知道模式是'many_not_digits,few_digits',所以逗号两边的左/右部分的大小之间存在很大的不平衡。
  • 您可以在不走动的情况下到达字符串的末尾,you can in Python because string indexing is constant time

然后你可以从最后开始,然后向后走,寻找逗号,这对于你的例子来说不是整体工作,而是从左边走,寻找逗号。

使用Python编写的代码比使用C编写的Python引擎代码慢,对吧?它真的会更快吗?

  1. 制作一个字符串" aaaaa ....,12"
  2. 使用timeit模块比较每种方法 - 分割或右步。
  3. Timeit会运行一些代码。
  4. 延长" aaaaaaaaaaaaaaaa ....,12"使它变得极端。
  5. 他们如何比较?

    • 字符串拆分:1400"""运行一百万次需要1秒。
    • 字符串拆分:4000""""""""""""""""
    • 正确的步行:1400"一次"的运行一百万次需要0.4秒。
    • 正确行走:999,999"""""""""      

    <!/ P>

    from timeit import timeit
    
    _split = """num = x.split(',')[-1]"""
    
    _rwalk = """
    i=-1
    while x[i] != ',':
        i-=1
    num = x[i+1:]
    """
    
    print(timeit(_split, setup='x="a"*1400 + ",12"'))
    print(timeit(_rwalk, setup='x="a"*999999 + ",12"'))
    

    e.g。

    1.0063155219977489     # "aaa...,12" for 1400 chars, string split
    0.4027107510046335     # "aaa...,12" for 999999 chars, rwalked. Faster.
    

    Try it online at repl.it

    我不认为这在算法上比O(n)更好,但是由于我所做的假设的约束,你比str.split()有更多的知识,并且可以利用它来跳过大部分的字符串并在实践中击败它 - 文本部分越长,数字部分越短,您受益越多。

答案 1 :(得分:2)

如果你担心从左边开始使用split,因为开头有很多不需要的字符,请使用rsplit。

s = "abcdef,12"
s.rsplit(",", 1)[-1]

这里,rsplit将从右侧开始拆分字符串,我们使用的可选第二个参数将使rsplit停止比它遇到的第一个逗号运算符更进一步。

(eg):
s = "abc,def,12"
s.rsplit(",", 1)[-1]
# Outputs 12
s = "abcdef12"
s.rsplit(",", 1)[-1]
# Outputs abcdef12

最终可以更简单,更清晰地获取数字字符串,而不是手动执行任何操作。

更不用说,如果我们想检查一下我们是否只获得数字,那将会容易得多。即使它是一个字符串列表。

def get_numbers(string_list, skip_on_error=True):
    numbers_list = []
    for input_string in string_list:
        the_number = input_string.rsplit(",", 1)[-1]
        if the_number.isdigit():
            numbers_list.append(the_number)
        elif skip_on_error:
            numbers_list.append("")
        else:
            raise Exception("Wrong Format occurred: %s" % (input_string))
    return numbers_list

如果您正在寻找更进一步的优化并确保大多数(如果不是全部)字符串的格式正确,您甚至可以使用try,除非您要使用整数列表而不是字符串列表。像这样:

# Instead of the if.. elif.. else construct
try:
    numbers_list.append(int(the_number))
except ValueError:
    if skip_on_error:
        numbers_list.append(0)
    else:
        raise Exception("Wrong Format occurred: %s" % (input_string))

但是永远记住Zen Of Python并使用split / rsplit遵循以下内容:

  1. 美丽胜过丑陋
  2. 明确胜过隐含
  3. 简单比复杂
  4. 更好
  5. 可读性计数
  6. 应该有一个 - 最好只有一个 - 显而易见的方法
  7. 还记得Donald Knuth:

      

    我们应该忘记效率很低,大约97%的时间说:过早优化是所有邪恶的根源。然而,我们不应该在那个关键的3%

    中放弃我们的机会

答案 2 :(得分:1)

使用split是优越的,因为它非常清晰和快速:

>>> s = "abcdef,12"
>>> s.split(',')[1]
'12'

另一种方法是使用indexfind

>>> s = "abcdef,12"
>>> s[s.find(',')+1:]
'12'

使用re的另一种方式:

>>> import re
>>> s = "abcdef,12"
>>> re.search(r',(.*)', s).group(1)
'12'

使用csv(以及io因此我不必将文件写入硬盘驱动器):

>>> import csv
>>> import io
>>> s = "abcdef,12"
>>> r = csv.reader(i)
>>> for line in r:
...     print(line[1])
...
12

我确定还有其他方法可以完成这项任务。这只是一个小样本。

答案 3 :(得分:1)

也许您可以尝试使用regular expression

import re

input_strings = ["abcdef,12", "gbhjjj,699"]

matcher = re.compile("\d+$")

for input_string in input_strings:
    is_matched = matcher.search(input_string)
    if is_matched:
        print(is_matched.group())

答案 4 :(得分:1)

我喜欢.partition()这类事情:

for text in ('gbhjjj,699', 'abcdef,12'):

    x, y, z = text.partition(',')

    number = int(z)

    print(number)

.split()不同,它总会返回三个值。

我有时会这样做,以强调我不关心某些价值观:

_, _, z = text.partition(',')