【问题标题】:Python 2 - iterating through csv with determinating specific lines as dicitonaryPython 2 - 遍历 csv 并将特定行确定为字典
【发布时间】:2014-06-14 13:14:02
【问题描述】:

this question 的帮助下,我从多个字典中生成了 csv(也可以阅读和编辑)。输出很简单

//Dictionary
key,value
key2,value2
//Dictionary2
key4, value4
key5, value5

我希望双反斜杠作为分隔符来创建新字典,但是每次调用 csv.reader(open("input.csv")) 都会通过行进行评估,所以我没有使用:

import csv
dict = {}
for key, val in csv.reader(open("input.csv")):
    dict[key] = val

谢谢你帮我..

编辑:我制作了这段......很好的“代码”......如果你能检查一下,我会很高兴的:

#! /usr/bin/python

import csv

# list of dictionaries 
l = []

# evalute throught csv
for row in csv.reader(open("test.csv")):

    if row[0].startswith("//"):

        # stripped "//" line is name for dictionary
        n = row[0][2:]

        # append stripped "//" line as name for dictionary

        #debug
        print n

        l.append(n)
        #debug print l[:]

    elif len(row) == 2:

        # debug
        print "len(row) %s" % len(row)
        # debug
        print "row[:] %s" % row[:]

        for key, val in row:
            # print key,val
            l[-1] = dic
            dic = {}
            dic[key] = val
# debug
for d in l:
    print l
    for key, value in d:
        print key, value

不幸的是我得到了这个错误:

DictName
len(row) 2
row[:] ['key', ' value']
Traceback (most recent call last):
  File "reader.py", line 31, in <module>
    for key, val in row:
ValueError: too many values to unpack

【问题讨论】:

  • 您的代码甚至不会尝试创建多个字典或查找'//Dictionary',那么您为什么会期待任何不同呢?考虑遍历文件;每行的两种情况是什么,你应该在每一种情况下做什么?
  • 非常感谢@jonrsharpe,用原始代码更新了。

标签: python csv dictionary key key-value


【解决方案1】:

考虑不使用 CSV

首先,您对数据问题的总体策略可能不是最优的。您的数据看起来越不呈表格形式,将其保存在 CSV 文件中的意义就越小(尽管您的需求并不太离谱)。

例如,使用 json 解决这个问题真的很容易:

import json

# First the data
data = dict(dict1=dict(key1="value1", key2="value2"),
            dict2=dict(key3="value3", key4="value4"))

# Convert and write
js = json.dumps(data)
f = file("data.json", 'w')
f.write(js)
f.close()

# Now read back
f = file("data.json", 'r')
data = json.load(f)
print data

按书面回答问题

但是,如果您真的确定了此策略,则可以按照 jonrsharpe 的建议做一些事情。您不能只使用csv 模块为您完成所有工作,实际上必须通过并过滤掉(和分割)“//”行。

import csv
import re

def header_matcher(line):
    "Returns something truthy if the line looks like a dict separator"
    return re.match("//", line)


# Open the file and ...
f = open("data.csv")
# create some containers we can populate as we iterate
data = []
d = {}

for line in f:
    if not header_matcher(line):
        # We have a non-header row, so we make a new entry in our draft dictionary
        key, val = line.strip().split(',')
        d[key] = val
    else:
        # We've hit a new header, so we should throw our draft dictionary in our data list
        if d:
            # ... but only if we actually have had data since the last header
            data.append(d)
            d = {}
# The very last chunk will need to be captured as well
if d:
    data.append(d)

# And we're done...
print data

这有点混乱,如果有任何需要转义逗号的机会,它会变得更加混乱。如果您需要,您可能会找到一种巧妙的方法将文件分块为您使用 CSV 阅读器读取的生成器,但它不会特别干净/容易(我开始了这样的方法,但看起来很痛苦...... )。这完全证明了您的方法可能是存储这些数据的错误方式。

如果您设置为 CSV,则另一种选择

如果您确实需要 CSV,但又不拘泥于您指定的确切数据格式,另一种方法是:在 CSV 文件中添加与数据应进入的字典相对应的列。想象一个看起来像这样的文件 (data2.csv):

dict1,key1,value1
dict1,key2,value2
dict2,key3,value3
dict2,key4,value4

现在我们可以做一些更干净的事情,如下所示:

import csv

data = dict()
for chunk, key, val in csv.reader(file('test2.csv')):
    try:
        # If we already have a dict for the given chunk id, this should add the key/value pair
        data[chunk][key] = val
    except KeyError:
        # Otherwise, we catch the exception and add a fresh dictionary with the key/value pair
        data[chunk] = {key: val}

print data

好多了...

如果有大量数据,并且空间是一个问题,那么做一些更接近您的想法的唯一好的论据是。但在大多数情况下,这种情况不太可能发生。

还有熊猫

哦,是的......另一种可能的解决方案是熊猫。我还没有太多使用它,所以我没有太多帮助,但是它提供了类似于group_by 函数的东西,如果你最终构建数据,它可以让你按第一列分组与 3 列 CSV 方法一样。

【讨论】:

  • 嗯,非常感谢!只要我只是编辑包含键和值的“数据文件”的人,json 应该没问题,但作为初学者,据我所知,csv 可读性很好,因此其他愿意更改字典的用户也会。所以我会坚持更难的方式和过滤。几个小时后(对我来说,编码是真正的斗争),我想出了与你在第二个示例中所做的类似的东西(不是那么干净),我将它编辑到我的帖子中,并期待明天尝试你的。非常感谢。
  • 是的; CSV 非常好有很多原因(如果您还没有的话,请查看 csvkit 命令行工具),所以我经常使用它。就更灵活的文本格式而言,Json 仍然具有相当的可读性,并且在许多情况下可以更清晰地表示数据的实际结构(使其最终更容易编辑),但这实际上取决于具体情况。不过,如果您真的想坚持使用 CSV,请考虑第三种方式。另外,我建议发布您提出的解决方案作为答案,以便其他人可以独立于问题本身对其进行审查和评论。
  • 初学者的错误,它不会再发生,我保证 :) 我会尝试这两个代码并更新我的解决方案。 Json 方式和 CSV。恐怕第三个不能满足我的需要,但它不会阻止我进行实验。
【解决方案2】:

我决定改用 json

阅读这对程序来说更容易,并且不需要过滤文本。用于在外部file.json 中生成数据库内部数据将服务于python 程序。

#! /usr/bin/python

import json

category1 = {"server name1":"ip address1","server name2":"ip address2"}

category2 = {"server name1":"ip address1","server name1":"ip address1"}

servers = { "category Alias1":category1,"category Alias2":category2}

js = json.dumps(servers)
f = file("servers.json", "w")
f.write(js)
f.close()

# Now read back
f = file("servers.json", "r")
data = json.load(f)
print data

所以输出是包含类别键的字典,而值是另一个字典。正是我想要的。

【讨论】:

    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 2021-09-23
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多