读取多个对象后访问JSON列

2024-04-20 15:17:24 发布

您现在位置:Python中文网/ 问答频道 /正文

问题

我在试图解决一个特定的问题时遇到了一个问题,我希望读入一个包含多个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对象列表中的一列,特别是对于每个项目上的一列信息:

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

问题


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

词典

但是我尝试使用字典,因为更新字典会覆盖先前更新的内容,例如键是相同的"prices",并且需要一些条件来测试新值是否高于或低于先前更新的值。你知道吗


Tags: 项目对象方法keyinjson内容列表
3条回答

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

因此,您可以使用Python的^{}^{}函数,并结合以下理解:

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

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

我从这个问题(我可能错了)中收集到的信息表明,您的问题似乎减少到以最高价格(例如)查找JSON对象(它实际上被加载到Python字典中),对吧?你知道吗

您可以按照您已经在做的方式加载内存中的所有文件(将其所有项放入allcontent字典列表),然后使用内置的^{}函数。你知道吗

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对象(又称dictionary):

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

但是,由于文件本身是一个iterable,您甚至不需要在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

ps01:我强烈建议您不要将infile的文件描述符命名为“file”,因为这会影响内置的^{}函数。你知道吗

PS 02: 根据你对问题的评论:

.load did work however as the input file im provided contains a list of objects there were errors when using .load as it is essentially just a string im reading from the file

如果要使用^{},则文件必须是有效的JSON。对于您在示例中提供的内容,我能想到的最接近有效的JSON是:

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

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

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

这是在python2.7中实现的。但实际上,即使有1000000行的文本,这里的收益也非常小。你知道吗

import time
import json
import string
import numpy as np

############################# GENERATE RANDOM DATA #############################

#letters = list(string.ascii_lowercase)
#random_data = ["""{"price": %d, "owner": "%s"}""" % (np.random.randint(1, 1000), 
#                ''.join(np.random.choice(letters, 6, replace=False))) for x 
#                in xrange(1000000)]
#
#with open('pseudo_json.txt', 'w') as outfile:
#    for line in random_data:
#        outfile.write(str(line) +'\n')


time1 = time.time()
#################################### METHOD 1 ##################################

running_max = 0
with open('pseudo_json.txt', 'r') as infile:
    for line in infile:
        price = json.loads(line)['price']
        if price > running_max:
            running_max = price

time2 = time.time()

#################################### METHOD 2 ##################################

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

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

time3 = time.time()

##################################### METHOD 3 ##############################

the_max = 0
with open("pseudo_json.txt", 'r') as f:
    the_max = (max(f, key=lambda x: json.loads(x)['price']))

time4 = time.time()

#################################### ORIGINAL ##################################

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

values = []

for line in allcontent:
    for key,value in line.items():
        values.append(value)

the_max = max(values)

time5 = time.time()

################################# READING FILE #################################

with open("pseudo_json.txt", 'r') as infile:
    for line in infile:
        pass

time6 = time.time()

################################### RESULTS ####################################

print "Without storage and max took: {}".format(time2 - time1)
print "With storage and using max took: {}".format(time3-time2)
print "Without storage but using max took: {}".format(time4 - time3)
print "Original took: {}".format(time5 - time4)
print "Reading file took: {}".format(time6 - time5)

相关问题 更多 >