用Python按特定值对JSON进行排序

7

你好,我正在尝试使用Python按"data_two"字段对以下JSON进行排序:

{
"1.2.3.4": {
    "data_one": 1,
    "data_two": 8,
    "list_one": [],
    "list_two": [
        "item_one"
    ],
    "data_three": "string1"
},
"5.6.7.8": {
    "data_one": 1,
    "data_two": 9,
    "list_two": [
        "item_one"
    ],
    "data_three": "string1",
    "data_four": "string2",
    "data_five": "string3"
}
}

我尝试使用类似于以下内容的方法

entries = sorted(json_data['1.2.3.4'], key=lambda k: k['data_two'])

然而,我一直没有什么运气/很困惑。我的最终目标是通过"data_two"值对所有JSON条目进行排序,其中每个条目的键是一个随机IP字符串。我对JSON的世界是新手,所以如果这是一个简单的问题,请原谅我,任何帮助将不胜感激。

谢谢


你不能对字典进行排序。Python 字典是无序的。为了排序,你必须先将字典转换为列表(或使用 OrderedDict)。 - Joel Cornett
2个回答

3
如果您可以控制数据的聚合方式,最好使用字典列表,并且IP应该是数据字典{..., 'ip': '127.0.0.1'}中的,而不是容器父字典中的

转换为保留元素顺序的容器

您只能对维护元素顺序的结构(如list)进行排序,例如有一些维护顺序的dict实现,例如OrderedDict

您始终可以将其转换为这些结构(如果数据量大或速度慢,则可能不是您的首选)

转换为列表[(key, value), ...]或列表[value, ...]

一个可能的方法是检索字典中的所有值,然后返回按您选择的字段排序的这些值的列表。

你还可以通过 ips_data.items() 排序返回的 (key, value),但这将创建一个新列表。其中 key 是 IP 地址,value 是 IP 数据。
sorted_list_of_keyvalues = sorted(ips_data.items(), key=item[1]['data_two'])

上面的列表是以 [(key1, value1), (key2, value2), ...] 的形式呈现的

您还可以提取值并删除键

sorted_list_of_values = [item[1] for item in sorted_list_of_keyvalues]

这个列表的形式为[value1, value2, ...] 请注意,您可能认为可以按值而不是(键,值)进行排序,但是您的数据在键中具有IP,您可能希望保留它。
转换为有序字典
如果您绝对想保持结构为字典,可以使用OrderedDict
from collections import OrderedDict
ordered_items = sorted(ips_data.items(), key=lambda item: item[1]['data_two'])
ordered_ips_data_dict = OrderedDict(ordered_items)

有序字典的行为类似于字典,但是键和元素迭代将保持元素的顺序。
或者,保持键的排序列表,并按照该顺序进行处理。
或者,您可以将该字典的键排序到列表中,然后按照该顺序处理字典。优点是您不必复制/转换数据。
>>> ips_data = {
... "1.2.3.4": {
...     "data_one": 1,
...     "data_two": 8,
...     "list_one": [],
...     "list_two": [
...         "item_one"
...     ],
...     "data_three": "string1"
... },
... "5.6.7.8": {
...     "data_one": 1,
...     "data_two": 9,
...     "list_two": [
...         "item_one"
...     ],
...     "data_three": "string1",
...     "data_four": "string2",
...     "data_five": "string3"
... }
... }
>>> ips_data.keys()
['1.2.3.4', '5.6.7.8']
>>> ips = ips_data.keys()

现在您可以通过字段 data_two 对键进行排序。
>>> sorted_ips = sorted(ips, key=lambda ip: ips_data[ip]['data_two'], reverse=True)
>>> sorted_ips
['5.6.7.8', '1.2.3.4']

排序完键后,您可以按照排序后的键对字典进行任何操作,例如按此顺序处理可能比将字典复制到新结构(如列表)中更有效率。

# Trivial example of processing that just puts the values into a list   
>>> [ips_data[ip] for ip in sorted_ips]
[{'data_three': 'string1', 'data_two': 9, 'data_five': 'string3', 'data_four': 'string2', 'list_two': ['item_one'], 'data_one': 1}, {'list_two': ['item_one'], 'data_two': 8, 'data_one': 1, 'data_three': 'string1', 'list_one': []}]
>>> 

1

看起来你尝试得很接近了。下面将为您提供一个排序后的元组列表,其中键位于第0个位置,值(即字典)位于第1个位置。您应该能够在此基础上完成您想要的操作。

entries = sorted(json_data.items(), key=lambda items: items[1]['data_two'])

所以例如:
{ "k1": {"data_one": 1, "data_two": 50 ...}, "k2": {"data_one": 50, "data_two": 2}}

会导致以下结果:

[("k2", {..."data_two": 2...}), ("k1", {..."data_two": 50...})]

希望这有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接