更改第一列中的数字
我知道用sed或awk可以更优雅地解决这个问题。不过我选择了用Python来处理。我的问题是,我想把数据文件的第一列重新编号,从1开始,一直到文件的行数。这种做法用readlines读取文件是否合适呢?对于小文件来说可能可以,但对于大文件我觉得不太行。所以这是我第一次尝试的结果,欢迎大家给我提意见。
#!/usr/bin/env python
import sys
try:
infilename = sys.argv[1]; outfilename = sys.argv[2];
except:
print "Usage is <script> inFile outFile"
ifile = open(infilename,'r')
ofile = open(outfilename, 'w')
lines = ifile.readlines();
i=1
for line in lines:
list = line.split();
list[0] = i
i += 1
for val in list:
ofile.write("%d " % int(val))
ofile.write('\n')
del list
ifile.close()
ofile.close()
5 个回答
在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后把它放到另一个地方。这就像是把水从一个杯子倒到另一个杯子一样。
当我们在写代码的时候,可能会遇到一些问题,比如数据的格式不对,或者数据没有按照我们想要的方式出现。这就像是你想喝水,但杯子里却是果汁,这时候你就需要想办法把果汁换成水。
有时候,程序会给我们一些错误提示,这些提示就像是一个指南,告诉我们哪里出了问题。我们需要仔细阅读这些提示,找到解决问题的方法。
总之,编程就像是在解决一个个小难题,我们需要耐心和细心,才能把这些问题一个个解决掉。
with open(infilename,'r') as ifile:
with open(outfilename, 'w') as ofile:
for (nr, line) in enumerate(ifile):
line = line.split()
line[0] = nr
line.append('\n')
ofile.write(' '.join(line))
#!/usr/bin/env python
import sys
try:
ifile = open(sys.argv[1], 'r')
ofile = open(sys.argv[2], 'w+')
except:
print "Usage is <script> inFile outFile"
else:
for i, line in enumerate(ifile, start=1):
items = [str(i)] + line.split()[1:]
ofile.write(' '.join(items) + '\n')
ifile.close()
ofile.close()
我想和大家聊聊我这个答案中的几个要点。首先是“try”块,这里我在检查能否打开文件。如果没有输入文件名,或者有文件无法打开,你就会看到使用说明。其实你可以把这个过程分开:先检查输入的文本,如果没有就返回使用说明;再尝试打开文件,如果失败了就返回文件打开失败的提示。或者,你也可以检查特定的错误类型,返回不同的错误信息。
接下来,枚举是一种方便的方式,可以让程序自动跟踪索引。在循环中,我把枚举的索引和读取行的“切片”(除了第一个项目以外的所有内容)结合在一起。然后我用空格把它们连接起来,并在最后加上换行符。
这样做既清晰又简洁。
你可以通过遍历文件,只在内存中保留当前行:
#!/usr/bin/env python
import sys
try:
# dont use ; !
infilename = sys.argv[1]
outfilename = sys.argv[2]
except:
print "Usage is <script> inFile outFile"
# you could use `with` here if you have a Python 2.7
ifile = open(infilename,'r')
ofile = open(outfilename, 'w')
# no need to count yourself, enumerate does that
# plus when you iterate over a file you get lines too
for i, line in enumerate(ifile, start=1):
# dont shadow builtins like `list`
parts = line.split()
parts[0] = i
# join is the inverse function to split
new_line = ' '.join("%d" % int(val) for val in parts)
ofile.write(new_line + '\n')
ifile.close()
ofile.close()
@Umut Tabak: ("%d" % int(val) for val in parts)
是一种叫做 生成器表达式 的东西,它有点像懒惰的列表。它给出的结果和列表推导式 ["%d" % int(val) for val in parts]
是一样的,但它并不会真正创建一个列表。
顺便说一下,for 循环的写法可以更简短,但稍微有点不同,因为它不再强制要求所有行都是 int
类型了:
for i, line in enumerate(ifile, start=1):
parts = line.split()
parts[0] = "%d" % i
new_line = ' '.join(parts)
ofile.write(new_line + '\n')