有没有一种 pythonic 方法来处理树结构的字典键?
Is there a pythonic way to process tree-structured dict keys?
我正在寻找一个 pythonic 习惯用法来将键列表和值转换为嵌套这些键的字典。例如:
dtree(["a", "b", "c"]) = 42
or
dtree("a/b/c".split(sep='/')) = 42
会 return 嵌套字典:
{"a": {"b": {"c": 42}}}
这可用于将一组具有分层键的值转换为树:
dtree({
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 })
would result in:
{ "a": {
"b": {
"c": 10,
"d": 20 },
"e": foo",
"f": False },
"g": 30 }
我可以编写一些 FORTRANish 代码来使用蛮力和多个循环进行转换,也许 collections.defaultdict
,但它似乎是一种具有拆分和连接以及切片和理解的语言应该有一个原语来转换一个字符串列表 ["a","b","c"]
到嵌套字典键 ["a"]["b"]["c"]
中。在 dict 表达式字符串上不使用 eval
的最短方法是什么?
I'm looking for a pythonic idiom to turn a list of keys and a value into a dict with those keys nested.
reduce(lambda v, k: {k: v}, reversed("a/b/c".split("/")), 42)
This could be used to turn a set of values with hierarchical keys into a tree
def hdict(keys, value, sep="/"):
return reduce(lambda v, k: {k: v}, reversed(keys.split(sep)), value)
def merge_dict(trg, src):
for k, v in src.items():
if k in trg:
merge_dict(trg[k], v)
else:
trg[k] = v
def hdict_from_dict(src):
result = {}
for sub_hdict in map(lambda kv: hdict(*kv), src.items()):
merge_dict(result, sub_hdict)
return result
data = {
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }
print(hdict_from_dict(data))
使用collections.defaultdict
的另一种整体解决方案
import collections
def recursive_dict():
return collections.defaultdict(recursive_dict)
def dtree(inp):
result = recursive_dict()
for keys, value in zip(map(lambda s: s.split("/"), inp), inp.values()):
reduce(lambda d, k: d[k], keys[:-1], result)[keys[-1]] = value
return result
import json
print(json.dumps(dtree({
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }), indent=4))
或者只是为了笑,因为 reduce
是自切片面包以来最酷的东西,你可以通过使用它两次来节省一个 SLOC :-)
def dmerge(x, y):
result = x.copy()
k = next(iter(y))
if k in x:
result[k] = dmerge(x[k], y[k])
else:
result.update(y)
return result
def hdict(keys, value, sep="/"):
return reduce(lambda v, k: {k: v}, reversed(keys.split(sep)), value)
def hdict_from_dict(src):
return reduce(lambda x, y: dmerge(x, y), [hdict(k, v) for k, v in src.items()])
data = {
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }
print("flat:", data)
print("tree:", hdict_from_dict(data))
我正在寻找一个 pythonic 习惯用法来将键列表和值转换为嵌套这些键的字典。例如:
dtree(["a", "b", "c"]) = 42
or
dtree("a/b/c".split(sep='/')) = 42
会 return 嵌套字典:
{"a": {"b": {"c": 42}}}
这可用于将一组具有分层键的值转换为树:
dtree({
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 })
would result in:
{ "a": {
"b": {
"c": 10,
"d": 20 },
"e": foo",
"f": False },
"g": 30 }
我可以编写一些 FORTRANish 代码来使用蛮力和多个循环进行转换,也许 collections.defaultdict
,但它似乎是一种具有拆分和连接以及切片和理解的语言应该有一个原语来转换一个字符串列表 ["a","b","c"]
到嵌套字典键 ["a"]["b"]["c"]
中。在 dict 表达式字符串上不使用 eval
的最短方法是什么?
I'm looking for a pythonic idiom to turn a list of keys and a value into a dict with those keys nested.
reduce(lambda v, k: {k: v}, reversed("a/b/c".split("/")), 42)
This could be used to turn a set of values with hierarchical keys into a tree
def hdict(keys, value, sep="/"):
return reduce(lambda v, k: {k: v}, reversed(keys.split(sep)), value)
def merge_dict(trg, src):
for k, v in src.items():
if k in trg:
merge_dict(trg[k], v)
else:
trg[k] = v
def hdict_from_dict(src):
result = {}
for sub_hdict in map(lambda kv: hdict(*kv), src.items()):
merge_dict(result, sub_hdict)
return result
data = {
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }
print(hdict_from_dict(data))
使用collections.defaultdict
的另一种整体解决方案
import collections
def recursive_dict():
return collections.defaultdict(recursive_dict)
def dtree(inp):
result = recursive_dict()
for keys, value in zip(map(lambda s: s.split("/"), inp), inp.values()):
reduce(lambda d, k: d[k], keys[:-1], result)[keys[-1]] = value
return result
import json
print(json.dumps(dtree({
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }), indent=4))
或者只是为了笑,因为 reduce
是自切片面包以来最酷的东西,你可以通过使用它两次来节省一个 SLOC :-)
def dmerge(x, y):
result = x.copy()
k = next(iter(y))
if k in x:
result[k] = dmerge(x[k], y[k])
else:
result.update(y)
return result
def hdict(keys, value, sep="/"):
return reduce(lambda v, k: {k: v}, reversed(keys.split(sep)), value)
def hdict_from_dict(src):
return reduce(lambda x, y: dmerge(x, y), [hdict(k, v) for k, v in src.items()])
data = {
"a/b/c": 10,
"a/b/d": 20,
"a/e": "foo",
"a/f": False,
"g": 30 }
print("flat:", data)
print("tree:", hdict_from_dict(data))