将带有类JSON对象的文本文件解析为CSV
我有一个包含键值对的文本文件,最后两个键值对包含类似JSON的对象,我想将其拆分为列并使用其他值,使用键作为列标题。前三行中的数据文件input.txt
的是这样的:将带有类JSON对象的文本文件解析为CSV
InnerDiameterOrWidth::0.1,InnerHeight::0.1,Length2dCenterToCenter::44.6743867864386,Length3dCenterToCenter::44.6768028159989,Tag::<NULL>,{StartPoint::7858.35924983374[%2C]1703.69341358077[%2C]-3.075},{EndPoint::7822.85045874375[%2C]1730.80294308742[%2C]-3.53962362760298}
InnerDiameterOrWidth::0.1,InnerHeight::0.1,Length2dCenterToCenter::57.8689351603823,Length3dCenterToCenter::57.8700464193429,Tag::<NULL>,{StartPoint::7793.52927597915[%2C]1680.91224357457[%2C]-3.075},{EndPoint::7822.85045874375[%2C]1730.80294308742[%2C]-3.43363070193163}
InnerDiameterOrWidth::0.1,InnerHeight::0.1,Length2dCenterToCenter::68.7161350545728,Length3dCenterToCenter::68.7172034962765,Tag::<NULL>,{StartPoint::7858.35924983374[%2C]1703.69341358077[%2C]-3.075},{EndPoint::7793.52927597915[%2C]1680.91224357457[%2C]-3.45819643838485}
,我们终于想出了一些工作,但必须有一个更好的方法:
import csv
with open('input.txt', 'rb') as fin, open('output.csv', 'wb') as fout:
reader = csv.reader(fin)
writer = csv.writer(fout)
for i, line in enumerate(reader):
mysplit = [item.split('::') for item in line if item.strip()]
if not mysplit: # blank line
continue
keys, vals = zip(*mysplit)
start_vals = [item.split('[%2C]') for item in mysplit[-2]]
end_vals = [item.split('[%2C]') for item in mysplit[-1]]
a=list(keys[0:-2])
a.extend(['start1','start2','start3','end1','end2','end3'])
b=list(vals[0:-2])
b.append(start_vals[1][0])
b.append(start_vals[1][1])
b.append(start_vals[1][2][:-1])
b.append(end_vals[1][0])
b.append(end_vals[1][1])
b.append(end_vals[1][2][:-1])
if i == 0:
# if first line: write header
writer.writerow(a)
writer.writerow(b)
产生输出文件output.csv
,看起来像这样
InnerDiameterOrWidth,InnerHeight,Length2dCenterToCenter,Length3dCenterToCenter,Tag,start1,start2,start3,end1,end2,end3
0.1,0.1,44.6743867864386,44.6768028159989,<NULL>,7858.35924983374,1703.69341358077,-3.075,7822.85045874375,1730.80294308742,-3.53962362760298
0.1,0.1,57.8689351603823,57.8700464193429,<NULL>,7793.52927597915,1680.91224357457,-3.075,7822.85045874375,1730.80294308742,-3.43363070193163
0.1,0.1,68.7161350545728,68.7172034962765,<NULL>,7858.35924983374,1703.69341358077,-3.075,7793.52927597915,1680.91224357457,-3.45819643838485
我们不想写这样的代码在未来。
什么是阅读这样的数据的最佳方式是什么?
我会使用:
from itertools import chain
import csv
_header_translate = {
'StartPoint': ('start1', 'start2', 'start3'),
'EndPoint': ('end1', 'end2', 'end3')
}
def header(col):
header = col.strip('{}').split('::', 1)[0]
return _header_translate.get(header, (header,))
def cleancolumn(col):
col = col.strip('{}').split('::', 1)[1]
return col.split('[%2C]')
def chainedmap(func, row):
return list(chain.from_iterable(map(func, row)))
with open('input.txt', 'rb') as fin, open('output.csv', 'wb') as fout:
reader = csv.reader(fin)
writer = csv.writer(fout)
for i, row in enumerate(reader):
if not i: # first row, write header first
writer.writerow(chainedmap(header, row))
writer.writerow(chainedmap(cleancolumn, row))
的cleancolumn
方法需要你的任何列,并且去掉括号,第一::
和分裂的前去除一切后,返回一个元组(可能只有一个值)嵌入'逗号'。通过使用itertools.chain.from_iterable()
,我们再次将csv编写器中从列中生成的一系列元组转换为一个列表。
当处理第一行时,我们从相同的列中生成一个标题行,将StartPoint
和EndPoint
标题替换为6个扩展标题。
好的答案。任何你喜欢的原因'如果不是我'结束'如果我=='?对我来说,你并不是问“它是否存在?”,你正在检查它是否为值0. – daveydave400 2013-03-04 21:34:48
@ daveydave400:Python中的numeric 0总是为false。所以是空序列和集合(字典,集合,列表,元组,字符串等)。我的眼睛更轻松,更清洁。 – 2013-03-04 21:35:12
我知道这是准确的,并且空序列评估为false,当我真正检查一个值时,我个人更喜欢“== X”,并且想知道除了偏好之外是否还有其他原因。当我检查空序列时,如果检查无是“无”或“不是无”,则使用“不是X”。 – daveydave400 2013-03-04 21:39:43
没有什么类似JSON的输入格式。唯一与远程相关的思想是花括号和逗号,但比较结束。 – 2013-03-04 21:10:33
我想几天前有人问过这样的问题,我会尽力找到它。或者,也许这是这个问题的延续?编辑:(http://*.com/questions/15190260/python-csv-read-write-remove-and-replace-plus-end-of-line-is-json-format/15190741) – daveydave400 2013-03-04 21:25:29