gpt4 book ai didi

python - 在 Python 中拆分字符串的最有效方法

转载 作者:IT老高 更新时间:2023-10-28 22:18:51 25 4
gpt4 key购买 nike

我当前的 Python 项目需要大量的字符串拆分来处理传入的包。由于我将在一个相当慢的系统上运行它,我想知道最有效的方法是什么。字符串的格式如下:

Item 1 | Item 2 | Item 3 <> Item 4 <> Item 5

解释:这个特定的例子来自一个列表,其中前两个项目是标题和日期,而项目 3 到项目 5 将被邀请的人(这些人的数量可以是从零到 n 的任何值,其中 n是服务器上的注册用户数)。

据我所知,我有以下选择:

  1. 反复使用split()
  2. 使用正则表达式和正则表达式函数
  3. 其他一些我还没有想到的 Python 函数(可能还有一些)

解决方案 1 包括在 | 处拆分然后在 <> 处拆分结果列表的最后一个元素对于这个例子,虽然解决方案 2 可能会导致如下正则表达式:

((.+)|)+((.+)(<>)?)+

好吧,这个正则表达式太可怕了,我自己也能看出来。它也未经测试。但你明白了。

现在,我正在寻找 a) 花费最少时间和 b) 理想情况下使用最少内存的方式。如果两者中只有一个是可能的,我希望时间更少。理想的解决方案也适用于有更多项目以 | 分隔的字符串。和完全缺少 <> 的字符串.至少基于正则表达式的解决方案可以做到这一点。

我的理解是 split()会使用更多的内存(因为你基本上会得到两个结果列表,一个在 | 处拆分,第二个在 <> 处拆分),但我对 Python 的正则表达式实现知之甚少,无法判断正则表达式会执行。 split()如果涉及到不同数量的项目并且没有第二个分隔符,它也没有正则表达式那么动态。尽管如此,我仍然无法摆脱 Python 可以在没有正则表达式的情况下做得更好的印象,这就是我问的原因。

一些注意事项:

  • 是的,我可以对这两种解决方案进行基准测试,但是我正在尝试了解有关 Python 的一般知识以及它在这里的工作原理,如果我只是对这两个解决方案进行基准测试,我仍然不知道我错过了哪些 Python 函数.
  • 是的,只有高性能的东西才真正需要在这个级别进行优化,但正如我所说,我正在努力学习有关 Python 的东西。
  • 补充:在原来的问题中,我完全忘了提到我需要能够区分被|分隔的部分。从带有分隔符的部分 <> , 所以一个由 re.split(\||<>,input) 生成的简单平面列表(如 proposed by obmarg )不会很好地工作。非常感谢符合此标准的解决方案。

总结问题:哪种解决方案最有效,原因是什么?

由于多个请求,我在 split() 上运行了一些 timeit -solution 和 obmarg 提出的第一个正则表达式,以及 solutions by mgibsonbr and duncan :

import timeit
import re

def splitit(input):
res0 = input.split("|")
res = []
for element in res0:
t = element.split("<>")
if t != [element]:
res0.remove(element)
res.append(t)
return (res0, res)

def regexit(input):
return re.split( "\||<>", input )


def mgibsonbr(input): # Solution by mgibsonbr
items = re.split(r'\||<>', input) # Split input in items
offset = 0
result = [] # The result: strings for regular items, lists for <> separated ones
acc = None
for i in items:
delimiter = '|' if offset+len(i) < len(input) and input[offset+len(i)] == '|' else '<>'
offset += len(i) + len(delimiter)
if delimiter == '<>': # Will always put the item in a list
if acc is None:
acc = [i] # Create one if doesn't exist
result.append(acc)
else:
acc.append(i)
else:
if acc is not None: # If there was a list, put the last item in it
acc.append(i)
else:
result.append(i) # Add the regular items
acc = None # Clear the list, since what will come next is a regular item or a new list
return result

def split2(input): # Solution by duncan
res0 = input.split("|")
res1, res2 = [], []
for r in res0:
if "<>" in r:
res2.append(r.split("<>"))
else:
res1.append(r)
return res1, res2

print "mgibs:", timeit.Timer("mgibsonbr('a|b|c|de|f<>ge<>ah')","from __main__ import mgibsonbr").timeit()
print "split:", timeit.Timer("splitit('a|b|c|de|f<>ge<>ah')","from __main__ import splitit").timeit()
print "split2:", timeit.Timer("split2('a|b|c|de|f<>ge<>ah')","from __main__ import split2").timeit()
print "regex:", timeit.Timer("regexit('a|b|c|de|f<>ge<>ah')","from __main__ import regexit").timeit()
print "mgibs:", timeit.Timer("mgibsonbr('a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import mgibsonbr").timeit()
print "split:", timeit.Timer("splitit('a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import splitit").timeit()
print "split:", timeit.Timer("split2('a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import split2").timeit()
print "regex:", timeit.Timer("regexit('a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import regexit").timeit()

结果:

mgibs: 14.7349407408
split: 6.403942732
split2: 3.68306812233
regex: 5.28414318792
mgibs: 107.046683735
split: 46.0844590775
split2: 26.5595985591
regex: 28.6513302646

目前,无论长度如何(至少在这个有限的数据集下),duncan 的 split2 看起来都击败了所有其他算法,而且看起来 mgibsonbr 的解决方案也存在一些性能问题(对此感到抱歉,但感谢解决方案)。

最佳答案

split() 在你的代码中表现如此糟糕,我有点惊讶,所以我仔细观察了一下,发现你正在调用 list.remove() 在内部循环中。此外,您在每个字符串上额外调用 split() 时间。摆脱这些,使用 split() 的解决方案在较短的字符串上击败了正则表达式,在较长的字符串上紧随其后。

import timeit
import re

def splitit(input):
res0 = input.split("|")
res = []
for element in res0:
t = element.split("<>")
if t != [element]:
res0.remove(element)
res.append(t)
return (res0, res)

def split2(input):
res0 = input.split("|")
res1, res2 = [], []
for r in res0:
if "<>" in r:
res2.append(r.split("<>"))
else:
res1.append(r)
return res1, res2

def regexit(input):
return re.split( "\||<>", input )

rSplitter = re.compile("\||<>")

def regexit2(input):
return rSplitter.split(input)

print("split: ", timeit.Timer("splitit( 'a|b|c|de|f<>ge<>ah')","from __main__ import splitit").timeit())
print("split2:", timeit.Timer("split2( 'a|b|c|de|f<>ge<>ah')","from __main__ import split2").timeit())
print("regex: ", timeit.Timer("regexit( 'a|b|c|de|f<>ge<>ah')","from __main__ import regexit").timeit())
print("regex2:", timeit.Timer("regexit2('a|b|c|de|f<>ge<>ah')","from __main__ import regexit2").timeit())
print("split: ", timeit.Timer("splitit( 'a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import splitit").timeit())
print("split2:", timeit.Timer("split2( 'a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import split2").timeit())
print("regex: ", timeit.Timer("regexit( 'a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import regexit").timeit())
print("regex2:", timeit.Timer("regexit2('a|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>aha|b|c|de|f<>ge<>ah')","from __main__ import regexit2").timeit())

结果如下:

split:  1.8427431439631619
split2: 1.0897291360306554
regex: 1.6694280610536225
regex2: 1.2277749050408602
split: 14.356198082969058
split2: 8.009285948995966
regex: 9.526430513011292
regex2: 9.083608677960001

当然 split2() 给出了你想要的嵌套列表,而正则表达式解决方案没有。

编译正则表达式将提高性能。它确实略有不同,但 Python 会缓存已编译的正则表达式,因此节省的空间不如您预期的那么多。我认为通常不值得为了速度而这样做(尽管在某些情况下可能如此),但通常值得让代码更清晰。

关于python - 在 Python 中拆分字符串的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9602856/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com