是否有更“Pythonic”的方式来组合CSV元素?

时间:2011-07-01 01:45:42

标签: python list csv

基本上我使用python cron从网上读取数据并将其放在CSV列表中:

.....
###1309482902.37
entry1,36,257.21,16.15,16.168
entry2,4,103.97,16.36,16.499
entry3,2,114.83,16.1,16.3
entry4,130.69,15.6737,16.7498
entry5,5.20,14.4,17
$$$
###1309482902.37
entry1,36,257.21,16.15,16.168
entry2,4,103.97,16.36,16.499
entry3,2,114.83,16.1,16.3
entry4,130.69,15.6737,16.7498
entry5,5.20,14.4,17
$$$

.....

我的代码基本上是进行正则表达式搜索,并通过###和$$$之间的所有匹配进行迭代,然后逐行遍历每个匹配,获取每一行并用逗号分割。你可以看到一些条目有4个逗号,有些条目有5个。这是因为我愚蠢而且没有意识到网络资源中的逗号是4位数。 IE

entry1,36,257.21,16.15,16.168

真的是

entry1,36257.21,16.15,16.168

我已经收集了大量数据并且不想重写,所以我想到了一个繁琐的解决方法。有更多的pythonic方法吗?

===

contents = ifp.read()

#Pull all entries from the market data
for entry in re.finditer("###(.*\n)*?\$\$\$",contents):

    dataSet = contents[entry.start():entry.end()]
    dataSet = dataSet.split('\n');

    timeStamp = dataSet[0][3:]
    print timeStamp

    for i in xrange(1,8):
        splits = dataSet[i].split(',')
        if(len(splits) == 5):
            remove = splits[1]
            splits[2] = splits[1] + splits[2]
            splits.remove(splits[1])
        print splits
        ## DO SOME USEFUL WORK WITH THE DATA ##

===

4 个答案:

答案 0 :(得分:2)

我使用Python的csv module读取CSV文件,修复我遇到它们时损坏的行,然后使用csv.writer将CSV写回。像这样(假设您的原始文件,错误位置的逗号为ugly.csv,新的,已清理的输出文件将为pretty.csv):

import csv

inputCsv = csv.reader(open("ugly.csv", "rb"))
outputCsv = csv.writer(open("pretty.csv", "wb"))

for row in inputCsv:
  if len(row) >= 5:
    row[1] = row[1] + row[2] #note that csv entries are strings, so this is string concatenation, not addition
    del row[2]
  outputCsv.writerow(row)

干净简单,而且,由于您正在使用正确的CSV解析器和编写器,因此您不必担心引入任何新的奇怪角落案例(如果您在第一个脚本中使用了此解析Web结果,输入数据中的逗号将被转义)。

答案 1 :(得分:0)

通常csv模块用于处理所有格式的CSV文件。

然而,在这里你有逗号这种丑陋的情况,所以一个丑陋的黑客是合适的。我没有看到一个干净的解决方案,所以我认为可以采取任何有效的方法。

顺便说一下,这条线似乎是多余的:

remove = splits[1]

答案 2 :(得分:0)

其他人建议您使用csv来解析文件,这是一个很好的建议。但它没有直接解决另一个问题 - 即,您正在处理由数据部分组成的文件。通过将文件转换为单个字符串然后使用正则表达式来解析该大字符串,您将丢弃该文件的关键点。另一种策略是编写一个可以解析文件的方法,一次产生一个部分。

def read_next_section(f):
    for line in f:
        line = line.strip()
        if line.startswith('#'):
            # Start of a new section.
            ts = line[3:]
            data = []
        elif line.startswith('$'):
            # End of a section.
            yield ts, data
        else:
            # Probably a good idea to use csv, as others recommend.
            # Also, write a method to deal with extra-comma problem.
            fields = line.split(',')
            data.append(fields)

with open(sys.argv[1]) as input_file:
    for time_stamp, section in read_next_section(input_file):
        # Do stuff.

答案 3 :(得分:0)

编写此代码块的更多pythonic方法

for i in xrange(1,8):
    splits = dataSet[i].split(',')
    if(len(splits) == 5):
        remove = splits[1]
        splits[2] = splits[1] + splits[2]
        splits.remove(splits[1])
    print splits

将是

for row in dataSet:
    name, data = row.split(',', 1)
    print [name] + data.rsplit(',', 2)