[英]Python: Need a hint on reading blocks of data from a text file
I have a file with data like this: 我有一个包含这样的数据的文件:
# 0 867.691994 855.172889 279.230411 -78.951239 55.994189 -164.824148
# 0 872.477810 854.828159 279.690170 -78.950558 55.994391 -164.823700
...
893.270609 1092.179289 184.692319
907.682255 1048.809187 112.538457
...
# 0 877.347791 854.481104 280.214892 -78.949869 55.994596 -164.823240
...
893.243290 1091.395104 184.726720
907.682255 1048.809187 112.538457
...
# 0 882.216053 854.135168 280.745489 -78.948443 55.996206 -164.821887
and I would like to read only lines between the comment lines in the following way: I read all the lines between two neighbouring comments into some array (without saving into a file), and work with it, then read the next block into array, and so on. 我想通过以下方式只读取注释行之间的行:我将两个相邻注释之间的所有行读入某个数组(不保存到文件中),并使用它,然后将下一个块读入数组,等等。
I managed to make it reading one block: 我设法让它读取一个块:
def main():
sourceFile = 'test.asc'
print 'Extracting points ...'
extF = open(sourceFile, 'r')
block, cursPos = readBlock(extF)
extF.close()
print 'Finished extraction'
def readBlock(extF):
countPnts = 0
extBlock = []
line = extF.readline()
while not line.startswith('#'):
extPnt = Point(*[float(j) for j in line.split()])
countPnts += 1
extBlock.append(extPnt)
line = extF.readline()
cursPos = extF.tell()
print 'Points:', countPnts
print 'Cursor position:', cursPos
return extBlock, cursPos
It works perfectly but only for one block of data. 它完美地工作,但仅适用于一个数据块。 I cannot make it iterating between commented lines from one block to another.
我不能让它在从一个块到另一个块的注释行之间进行迭代。 I was thinking about the cursor position but could not realise that.
我正在考虑光标位置,但无法实现。 Please give me some tips about this.
请给我一些关于此的提示。 Thank you.
谢谢。
Update I implemented the idea of MattH as following: 更新我实现了MattH的想法如下:
def blocks(seq):
buff = []
for line in seq:
if line.startswith('#'):
if buff:
#yield "".join(buff)
buff = []
else:
# I need to make those numbers float
line_spl = line.split()
pnt = [float(line_spl[k]) for k in range(len(line_spl))]
#print pnt
buff.append(Point(*pnt))
if buff:
yield "".join(buff)
Then, if I run it: 然后,如果我运行它:
for block in blocks(extF.readlines()):
print 'p'
I have just empty window although print 'p'
is inside the for
-loop. 虽然
print 'p'
在for
-loop中,但我只有空窗口。 So, there is a couple of questions: 所以,有几个问题:
What does the 什么是
if buff:
yield "".join(buff)
do? 做? When I comment it nothing changes...
当我评论它没有任何变化......
Why commands inside the for
-loop does not work? 为什么
for
-loop中的命令不起作用?
This function is generator, so I do not have access to the lines which were processed before, do I? 这个函数是生成器,所以我无法访问之前处理过的行,是吗?
Solution 解
I managed to do it myself using ideas of MattH and Ashwini Chaudhari. 我设法使用MattH和Ashwini Chaudhari的想法自己做。 Finally, I got this:
最后,我得到了这个:
def readBlock(extF):
countPnts = 0
extBlock = []
line = extF.readline()
if line.startswith('#'):
line = extF.readline()
else:
while not line.startswith('#'):
extPnt = Point(*[float(j) for j in line.split()])
countPnts += 1
extBlock.append(extPnt)
line = extF.readline()
return extBlock, countPnts
And run it with: 并运行它:
while extF.readline():
block, pntNum = readBlock(extF)
It works exactly as I need. 它完全按照我的需要工作。
Thanks everybody. 谢谢大家。
Here are two simple generators, one that yields all non-comment blocks and the other only the non-comment blocks between comments. 这里有两个简单的生成器,一个生成所有非注释块,另一个生成注释之间的非注释块。 Updated for the two different possibilities and updated to have line splitting and joining in the same function for consistency.
针对两种不同的可能性进行了更新,并进行了更新以使线分割和连接在同一功能中以保持一致性。
sample = """Don't yield this
# 0 867.691994 855.172889 279.230411 -78.951239 55.994189 -164.824148
# 0 872.477810 854.828159 279.690170 -78.950558 55.994391 -164.823700
...
893.270609 1092.179289 184.692319
907.682255 1048.809187 112.538457
...
# 0 877.347791 854.481104 280.214892 -78.949869 55.994596 -164.823240
...
893.243290 1091.395104 184.726720
907.682255 1048.809187 112.538457
...
# 0 882.216053 854.135168 280.745489 -78.948443 55.996206 -164.821887
Don't yield this either"""
def blocks1(text):
"""All non-comment blocks"""
buff = []
for line in text.split('\n'):
if line.startswith('#'):
if buff:
yield "\n".join(buff)
buff = []
else:
buff.append(line)
if buff:
yield "\n".join(buff)
def blocks2(text):
"""Only non-comment blocks *between* comments"""
buff = None
for line in text.split('\n'):
if line.startswith('#'):
if buff is None:
buff = []
if buff:
yield "\n".join(buff)
buff = []
else:
if buff is not None:
buff.append(line)
for block in blocks2(sample):
print "Block:\n%s" % (block,)
Produces: 生产:
Block:
...
893.270609 1092.179289 184.692319
907.682255 1048.809187 112.538457
...
Block:
...
893.243290 1091.395104 184.726720
907.682255 1048.809187 112.538457
...
data.txt: data.txt中:
123456
1234
# 0 867.691994 855.172889 279.230411 -78.951239 55.994189 -164.824148
# 0 872.477810 854.828159 279.690170 -78.950558 55.994391 -164.823700
...
893.270609 1092.179289 184.692319
907.682255 1048.809187 112.538457
...
# 0 877.347791 854.481104 280.214892 -78.949869 55.994596 -164.823240
...
893.243290 1091.395104 184.726720
907.682255 1048.809187 112.538457
...
# 0 882.216053 854.135168 280.745489 -78.948443 55.996206 -164.821887
1234
12345
program: 程序:
with open('data.txt') as f:
lines=[x.strip() for x in f if x.strip()]
for i,x in enumerate(lines): #loop to find the first comment line
if x.startswith('#'):
ind=i
break
for i,x in enumerate(lines[::-1]): #loop to find the first comment line from the end
if x.startswith('#'):
ind1=i
break
for x in lines[ind+1:-ind1-1]:
if not x.startswith('#'):
print x
output: 输出:
...
893.270609 1092.179289 184.692319
907.682255 1048.809187 112.538457
...
...
893.243290 1091.395104 184.726720
907.682255 1048.809187 112.538457
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.