使用Python为所有key递归映射一个JSON文件,同时记录每个key的"nesting"深度
Using Python to recursively map a JSON file for all keys, while also recording the depth of "nesting" for each key
背景:
我有一个很大的 JSON 文件(数十 GB),其中文件的每一“行”都是一个日志条目(也是 JSON 格式)。日志来自多个不同的来源,因此一个日志中的字段可能会或可能不会显示在任何其他日志中。换句话说,JSON 格式的“键”,以及键相互嵌套的程度,在日志之间是不一致的。
我的目标:
我需要能够找到任何给定日志中的所有键 [已完成],并跟踪哪些键嵌套在哪些其他键下 [这是我还没有解决的部分].
我目前的工作:
由于文件太大,我无法一次将文件全部加载到内存中,所以我一直在逐行检查它(逐个日志)。我已经编辑了实际内容,但假设文件的第一行(日志)如下所示:
{'foo': {'bar': 'data',
'biz': 'data'},
'baz': 'data',
'qux': {'quux': 'data',
'quuz': 'data'},
'corge': {'grault': {'garply': 'data'},
'waldo': {'fred': 'data',
'plugh': 'data'},
'xyzzy': 'data'},
'thud': 'data'}
我一直在使用这个代码...
def find_nested_dicts(d):
for k,v in d.items():
KEYS.append(k)
if isinstance(d[k], dict):
find_nested_dicts(d[k])
return KEYS
KEYS=[]
with open(full_geodata_path, "r") as f:
next_line = f.readline()
next_line_json = json.loads(next_line)
output = find_nested_dicts(next_line_json)
...产生这个:
output = [
'foo',
'bar',
'biz',
'baz',
'qux',
'quux',
'quuz',
'corge',
'grault',
'garply',
'waldo',
'fred',
'plugh',
'xyzzy',
'thud'
]
我不喜欢使用 KEYS
作为全局变量,但我无法让它在本地工作。
请注意,每个键附加到此列表的顺序很重要。键的名称很少包含任何指示它们嵌套在哪个父键下的内容。换句话说,我有意编写代码,以便将键附加到 output
列表的顺序与它们以 JSON 格式显示的顺序相同。
上面显示的结果是我的目标的一半。但是,我希望能够生成一个包含每个键的列表,以及检索它的嵌套深度。我正在尝试构建一个如下所示的列表:
output = [
('foo', 0),
('bar', 1),
('biz', 1),
('baz', 0),
('qux', 0),
('quux', 1),
('quuz', 1),
('corge', 0),
('grault', 1),
('garply', 2),
('waldo', 1),
('fred', 2),
('plugh', 2),
('xyzzy', 1),
('thud', 0)
]
这个函数可能是我得到的最接近的函数:
def find_nested_dicts(d, depth=0):
for k, v in d.items():
KEYS.append((k, depth))
depth += 1
if isinstance(v, dict):
find_nested_dicts(v, depth)
else:
depth -= 1
return KEYS
此尝试的问题是此函数只会导致“深度”计数器增加。
我尝试将递归映射到纸上,并尝试在 depth += 1
、depth -= 1
和 KEYS.append((k, depth))
语句中移动 for
和 if
以各种组合循环,希望获得更好的结果。
在这一点上,我不确定是否是我自己无法完全概念化递归,或者我正在尝试做的事情是否真的可以用普通 python 实现。非常感谢任何见解。
最后一点,我没有我试图解决此问题的机器的管理员权限,并且无法从我的个人机器访问此数据。从以前的项目中我知道我可以使用以下库:
import numpy as np
import os
import pandas as pd
import json
import itertools
from collections import Counter
import matplotlib.pyplot as plt
def foo(d, arr, n):
if isinstance(d, dict):
for k in d.keys():
arr.append((k, n))
foo(d[k], arr, n + 1)
ans = []
foo(data, ans, 0)
ans
# [('foo', 0),
# ('bar', 1),
# ('biz', 1),
# ('baz', 0),
# ('qux', 0),
# ('quux', 1),
# ('quuz', 1),
# ('corge', 0),
# ('grault', 1),
# ('garply', 2),
# ('waldo', 1),
# ('fred', 2),
# ('plugh', 2),
# ('xyzzy', 1),
# ('thud', 0)]
背景:
我有一个很大的 JSON 文件(数十 GB),其中文件的每一“行”都是一个日志条目(也是 JSON 格式)。日志来自多个不同的来源,因此一个日志中的字段可能会或可能不会显示在任何其他日志中。换句话说,JSON 格式的“键”,以及键相互嵌套的程度,在日志之间是不一致的。
我的目标:
我需要能够找到任何给定日志中的所有键 [已完成],并跟踪哪些键嵌套在哪些其他键下 [这是我还没有解决的部分].
我目前的工作:
由于文件太大,我无法一次将文件全部加载到内存中,所以我一直在逐行检查它(逐个日志)。我已经编辑了实际内容,但假设文件的第一行(日志)如下所示:
{'foo': {'bar': 'data',
'biz': 'data'},
'baz': 'data',
'qux': {'quux': 'data',
'quuz': 'data'},
'corge': {'grault': {'garply': 'data'},
'waldo': {'fred': 'data',
'plugh': 'data'},
'xyzzy': 'data'},
'thud': 'data'}
我一直在使用这个代码...
def find_nested_dicts(d):
for k,v in d.items():
KEYS.append(k)
if isinstance(d[k], dict):
find_nested_dicts(d[k])
return KEYS
KEYS=[]
with open(full_geodata_path, "r") as f:
next_line = f.readline()
next_line_json = json.loads(next_line)
output = find_nested_dicts(next_line_json)
...产生这个:
output = [
'foo',
'bar',
'biz',
'baz',
'qux',
'quux',
'quuz',
'corge',
'grault',
'garply',
'waldo',
'fred',
'plugh',
'xyzzy',
'thud'
]
我不喜欢使用 KEYS
作为全局变量,但我无法让它在本地工作。
请注意,每个键附加到此列表的顺序很重要。键的名称很少包含任何指示它们嵌套在哪个父键下的内容。换句话说,我有意编写代码,以便将键附加到 output
列表的顺序与它们以 JSON 格式显示的顺序相同。
上面显示的结果是我的目标的一半。但是,我希望能够生成一个包含每个键的列表,以及检索它的嵌套深度。我正在尝试构建一个如下所示的列表:
output = [
('foo', 0),
('bar', 1),
('biz', 1),
('baz', 0),
('qux', 0),
('quux', 1),
('quuz', 1),
('corge', 0),
('grault', 1),
('garply', 2),
('waldo', 1),
('fred', 2),
('plugh', 2),
('xyzzy', 1),
('thud', 0)
]
这个函数可能是我得到的最接近的函数:
def find_nested_dicts(d, depth=0):
for k, v in d.items():
KEYS.append((k, depth))
depth += 1
if isinstance(v, dict):
find_nested_dicts(v, depth)
else:
depth -= 1
return KEYS
此尝试的问题是此函数只会导致“深度”计数器增加。
我尝试将递归映射到纸上,并尝试在 depth += 1
、depth -= 1
和 KEYS.append((k, depth))
语句中移动 for
和 if
以各种组合循环,希望获得更好的结果。
在这一点上,我不确定是否是我自己无法完全概念化递归,或者我正在尝试做的事情是否真的可以用普通 python 实现。非常感谢任何见解。
最后一点,我没有我试图解决此问题的机器的管理员权限,并且无法从我的个人机器访问此数据。从以前的项目中我知道我可以使用以下库:
import numpy as np
import os
import pandas as pd
import json
import itertools
from collections import Counter
import matplotlib.pyplot as plt
def foo(d, arr, n):
if isinstance(d, dict):
for k in d.keys():
arr.append((k, n))
foo(d[k], arr, n + 1)
ans = []
foo(data, ans, 0)
ans
# [('foo', 0),
# ('bar', 1),
# ('biz', 1),
# ('baz', 0),
# ('qux', 0),
# ('quux', 1),
# ('quuz', 1),
# ('corge', 0),
# ('grault', 1),
# ('garply', 2),
# ('waldo', 1),
# ('fred', 2),
# ('plugh', 2),
# ('xyzzy', 1),
# ('thud', 0)]