Tom*_*Tom 9 python string iterator generator
说我有以下内容:
dest = "\n".join( [line for line in src.split("\n") if line[:1]!="#"] )
Run Code Online (Sandbox Code Playgroud)
(即从多行字符串中删除以#开头的所有行src)
src是非常大的,所以我假设.split()将创建一个大的中间列表.我可以将列表理解更改为生成器表达式,但是我可以使用某种"xsplit"一次只能在一行上工作吗?我的假设是否正确?处理这个问题的最有效(内存)方法是什么?
澄清:这是由于我的代码内存不足造成的.我知道有一些方法可以完全重写我的代码来解决这个问题,但问题是关于Python:是否有一个版本的split()(或一个等效的习惯用法),它的行为类似于生成器,因此无法进行额外的工作副本src?
buffer = StringIO(src)
dest = "".join(line for line in buffer if line[:1]!="#")
Run Code Online (Sandbox Code Playgroud)
当然,如果你StringIO全程使用,这真的是最有意义的.它的工作方式与文件大致相同.您可以搜索,读取,写入,迭代(如图所示)等.
这是使用itertools进行常规拆分的一种方法
>>> import itertools as it
>>> src="hello\n#foo\n#bar\n#baz\nworld\n"
>>> line_gen = (''.join(j) for i,j in it.groupby(src, "\n".__ne__) if i)
>>> '\n'.join(s for s in line_gen if s[0]!="#")
'hello\nworld'
Run Code Online (Sandbox Code Playgroud)
groupby分别处理src中的每个char,因此性能可能不是很好,但它确实避免创建任何中间的大型数据结构
可能更好地花几行并制造发电机
>>> src="hello\n#foo\n#bar\n#baz\nworld\n"
>>>
>>> def isplit(s, t): # iterator to split string s at character t
... i=j=0
... while True:
... try:
... j = s.index(t, i)
... except ValueError:
... if i<len(s):
... yield s[i:]
... raise StopIteration
... yield s[i:j]
... i = j+1
...
>>> '\n'.join(x for x in isplit(src, '\n') if x[0]!='#')
'hello\nworld'
Run Code Online (Sandbox Code Playgroud)
re有一个叫做的方法finditer,也可以用于此目的
>>> import re
>>> src="hello\n#foo\n#bar\n#baz\nworld\n"
>>> line_gen = (m.group(1) for m in re.finditer("(.*?)(\n|$)",src))
>>> '\n'.join(s for s in line_gen if not s.startswith("#"))
'hello\nworld'
Run Code Online (Sandbox Code Playgroud)
比较性能是OP尝试实际数据的练习
| 归档时间: |
|
| 查看次数: |
1289 次 |
| 最近记录: |