读取多个对象后访问JSON列

时间:2016-11-02 17:10:16

标签: python json list dictionary

问题

我在尝试解决特定问题时遇到问题,我希望在包含多个json对象的文件中读取并同时访问每个对象的值。到目前为止,我让它像这样读取json对象:

with open(infile) as file:
    allcontent = []
    for line in file:
        allcontent.append(json.loads(line))

列表的内容只是每个项目的json对象:

[{"price": 241, "owner": "brian"}]

[{"price": 243, "owner": "bob"}]

这可以工作,只需将每个json对象附加到列表中。但是,由于我希望计算列表中每个项目的最高价格,我无法理解在没有复杂循环的情况下执行操作的简单方法,并指定变量来跟踪每个列值。

我尝试循环遍历每个json对象并访问键和值,但我不想使用此方法,因为看起来应该有一种更简单的方法来从json对象列表中访问列,特别是对于just每个项目的1列信息:

for line in file:
    for key,value in line.items():
        print(key,value)

问题

使用此方法会打印出每个行的键和值,但是我需要一次访问所有行的价格以找到最高和最低的行。有比循环更简单的方法吗?例如allcontent['prices']

字典

我尝试使用字典,但更新字典会覆盖以前更新的内容,因为密钥是相同的"prices",并且需要许多条件来测试新值是高于还是低于之前更新了一个。

3 个答案:

答案 0 :(得分:3)

对于我从问题中收集的内容(我可能错了),你的问题似乎减少了找到JSON对象(实际上被加载到Python字典中)的最高价格(例如),对吗?

您可以按照您已经执行过的方式将所有文件加载到内存中(将所有项目放入allcontent词典列表中),然后使用内置的max函数

import json

with open("data.json", 'r') as f:
    allcontent = []
    for line in f:
        allcontent.append(json.loads(line))

print(max(allcontent, key=lambda x: x['price']))

...输出整个JSON对象(a.k.a 字典):

{u'owner': u'bob', u'price': 243}

但是,由于文件本身是可迭代的,因此您甚至不需要在allcontent中预加载它。你可以这么做:

with open("data.json", 'r') as f:
    print(max(f, key=lambda x: json.loads(x)['price']))

所有这些假设您的文件看起来完全如下:

{"price":241,"owner":"brian"}
{"price":243,"owner":"bob"}

...这是无效的JSON

PS 01:我强烈建议您不要为infile的文件描述符"文件" ,因为这会影响内置的file函数。

PS 02: 根据你在问题中的评论:

  然而,

.load确实有效,因为我提供的输入文件包含一个对象列表,当使用.load时它有错误,因为它实际上只是一个从文件中读取的字符串

如果您想使用json.load,您的文件需要是有效的JSON。对于您在示例中提供的内容,我能想到的最接近的有效JSON是:

[
 {"price":241,"owner":"brian"},
 {"price":243,"owner":"bob"}
]

请注意,它会创建一个列表(以[开头,以]结尾),并且列表中的每个项都用逗号分隔(最后一个除外)。我亲自使用页面JSONLint.com检查Json的有效性(但我确定还有很多其他人)

答案 1 :(得分:2)

我做了一些基准测试。我能得到的最快的是csr中的1mil行(我已经将代码散列出来以生成数据,但是unhash并制作自己的代码需要30秒)。 Method 1Method 2是我对BorrajaX答案的回应(前者实际上允许您保留所有读入数据以供进一步使用)。 Method 3是您的原创,有希望保持Method 4的价值。我删除了所有print语句。

这是在Python 2.7中。但实际上,即使有1,000,000行文本,这里的收益实际上也很小。

print

答案 2 :(得分:1)

json.loads的结果通常是*常规Python字典。这意味着,在您的示例中,allcontent变量只是一个字典列表。

因此,您可以使用Python的minmax函数,并结合理解:

>>> allcontent = [{'price': 1}, {'price': 2}]
>>> min((thing['price'] for thing in allcontent))
1

*:当然,如果你json.loads("0"),你只需得到一个整数。