如何在字符串Python中获取:之前的所有内容


102

我正在寻找一种方法来在:之前获取字符串中的所有字母,但是我不知道从哪里开始。我会使用正则表达式吗?如果可以,怎么办?

string = "Username: How are you today?"

有人可以给我示范我可以做什么吗?

Answers:


169

只需使用该split功能。它返回一个列表,因此您可以保留第一个元素:

>>> s1.split(':')
['Username', ' How are you today?']
>>> s1.split(':')[0]
'Username'

12
要么限制拆分,要么在这种情况下使用s1.partition(':')[0]
乔恩·克莱门茨

谢谢你,这是非常有用和有益的。加上它是一个很大的帮助,谢谢!
0Cool

1
不要使用split,因为它会处理所有的':'并创建一个完整的数组,不适用于较长的字符串。请参阅@Hackaholic使用索引的方法。只是有人还建议使用一种正则表达式,显然效果不佳。还必须有一个python选项来执行.substringBefore()的基于索引的标准操作。为了方便起见,还应该有.substringBeforeLast()之类的变体(不应重复代码)。注意关于分区的要点-是的,在':'之后的处理较少,但仍返回<class'tuple'> ::('1',':','2:3')而不是'1'。
arntg

43

使用index

>>> string = "Username: How are you today?"
>>> string[:string.index(":")]
'Username'

该索引将给您以下位置 :在字符串中,然后可以对其进行切片。

如果要使用正则表达式:

>>> import re
>>> re.match("(.*?):",string).group()
'Username'                       

match 从字符串开头开始匹配。

你也可以使用 itertools.takewhile

>>> import itertools
>>> "".join(itertools.takewhile(lambda x: x!=":", string))
'Username'

3
此方法(string [:string.index(“:”)])可能比拆分更干净
Damien

为了提高速度,请不要使用正则表达式-请使用此处提到的第一个索引选项。正则表达式显然不那么有效。还必须有一个python选项来执行.substringBefore()的基于索引的标准操作。为了方便起见,还应该有.substringBeforeLast()之类的变体(不应重复代码)。建议更新此答案,以解释为什么索引效果更好,然后为什么将其用于其他方法,包括在fredtantini的回应中现在被选为更高的方法。
arntg

如果不存在,索引将失败。
Marc

18

你不需要regex这个

>>> s = "Username: How are you today?"

您可以使用split方法拆分的字符串':'的字符

>>> s.split(':')
['Username', ' How are you today?']

并切出元素[0]以获得字符串的第一部分

>>> s.split(':')[0]
'Username'

7

我已经在Python 3.7.0(IPython)下对这些各种技术进行了基准测试。

TLDR

  • 最快(当分割符号 c已知):预编译的正则表达式。
  • 最快(否则): s.partition(c)[0]
  • 安全(即何时c可能不在s):分区,拆分。
  • 不安全:索引,正则表达式。

import string, random, re

SYMBOLS = string.ascii_uppercase + string.digits
SIZE = 100

def create_test_set(string_length):
    for _ in range(SIZE):
        random_string = ''.join(random.choices(SYMBOLS, k=string_length))
        yield (random.choice(random_string), random_string)

for string_length in (2**4, 2**8, 2**16, 2**32):
    print("\nString length:", string_length)
    print("  regex (compiled):", end=" ")
    test_set_for_regex = ((re.compile("(.*?)" + c).match, s) for (c, s) in test_set)
    %timeit [re_match(s).group() for (re_match, s) in test_set_for_regex]
    test_set = list(create_test_set(16))
    print("  partition:       ", end=" ")
    %timeit [s.partition(c)[0] for (c, s) in test_set]
    print("  index:           ", end=" ")
    %timeit [s[:s.index(c)] for (c, s) in test_set]
    print("  split (limited): ", end=" ")
    %timeit [s.split(c, 1)[0] for (c, s) in test_set]
    print("  split:           ", end=" ")
    %timeit [s.split(c)[0] for (c, s) in test_set]
    print("  regex:           ", end=" ")
    %timeit [re.match("(.*?)" + c, s).group() for (c, s) in test_set]

结果

String length: 16
  regex (compiled): 156 ns ± 4.41 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.3 µs ± 430 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            26.1 µs ± 341 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.8 µs ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.3 µs ± 835 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 4.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 256
  regex (compiled): 167 ns ± 2.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 694 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  index:            28.6 µs ± 2.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.4 µs ± 979 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            31.5 µs ± 4.86 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            148 µs ± 7.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

String length: 65536
  regex (compiled): 173 ns ± 3.95 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 613 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 515 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.2 µs ± 796 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.5 µs ± 377 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 4294967296
  regex (compiled): 165 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.9 µs ± 144 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 571 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.1 µs ± 472 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            28.1 µs ± 1.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            137 µs ± 6.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

为什么您认为索引不安全?
詹姆斯

2
s.index(c)c不在中时引发ValueError s。因此,当我确定要分区的字符串包含分隔符时,我认为它是安全的,否则是不安全的。
阿里斯蒂德

对于索引,c以s为单位,因此它并不安全并且仍然最快。
arntg

2

为此,partition()可能比split()更好,因为在没有定界符或更多定界符的情况下,它具有更好的可预测结果。


1
两者partitionsplit都将透明地使用空字符串或没有定界符。值得注意的是word[:word.index(':')],这两种情况都会弹出。
罗伯·霍尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.