给定一个复杂的 Python 字典或数组数据结构,我们希望找到所有非空结束叶子的数量。非空结束叶子是指数据结构中嵌套字典或数组的最后一个元素不为空。例如,对于以下嵌套字典:
x = {"top": {"middle" : [
{"nested": "value"},
{"nested":"val2"},
{"nested":""}
],
"last" : [
{"nested": [
{"first":1,"second":1},
{"first":0,"second":""}
]
},
{"nested": [
{"first":1,"second":1},
{"first":1,"second":2}
]
},
{"nested": [
{"first":1,"second":1},
{"first":"","second":""}
]
}
]
},
"other":1}
其中,"paths" 变量中的每个元素表示数据结构中从根节点到某个叶子节点的路径,例如:
vars = ["top.middle.XX.nested",
"top.last.XX.nested.XX.first",
"top.last.XX.nested.XX.second",
"other"]
我们希望编写一个函数 f(x, y),其中 x 是输入数据结构,y 是某个路径,该函数可以返回该路径下非空结束叶子的数量。例如:
f(x, "top.middle.XX.nested") = 2/3
f(x, "top.last.XX.nested.XX.first") = 5/6
f(x, "top.last.XX.nested.XX.second") = 4/6
f(x, "other") = 1
2、解决方案
我们可以使用递归算法来解决这个问题。具体步骤如下:
-
定义一个函数
byPath(tree, path),用于根据给定的路径path从数据结构tree中提取对应的值。如果path中包含 "XX",表示需要遍历该位置的所有元素,并将其值作为列表返回。否则,如果path中不包含 "XX",则直接返回tree中对应于path的值。 -
定义一个函数
count(result),用于统计给定结果result中非空元素的数量。如果result是一个列表,则遍历列表中的每个元素并累加非空元素的数量。如果result不是列表,则直接判断其是否为空。 -
定义一个函数
f(tree, path),用于根据给定的路径path从数据结构tree中提取非空结束叶子的数量。该函数首先使用byPath函数提取路径对应的值,然后使用count函数统计非空元素的数量。最后将统计结果作为分数返回,分数的分子是非空元素的数量,分母是总元素的数量。 -
使用
f函数对给定的路径列表vars中的每个路径进行处理,并输出结果。
代码示例:
def byPath(tree, path):
try:
head, tail = path.split('.', 1)
except:
return tree[path]
if head == 'XX':
return [byPath(node, tail) for node in tree]
else:
return byPath(tree[head], tail)
def count(result):
if isinstance(result, list):
total = 0
positive = 0
for e in result:
r = count(e)
total += r[1]
positive += r[0]
return (positive, total)
else:
return (0 if result == '' else 1, 1)
def f(tree, path):
return count(byPath(tree, path))
x = {"top": {"middle": [
{"nested": "value"},
{"nested": "val2"},
{"nested": ""}
],
"last": [
{"nested": [
{"first": 1, "second": 1},
{"first": 0, "second": ""}
]
},
{"nested": [
{"first": 1, "second": 1},
{"first": 1, "second": 2}
]
},
{"nested": [
{"first": 1, "second": 1},
{"first": "", "second": ""}
]
}
]
},
"other": 1}
vars = ["top.middle.XX.nested",
"top.last.XX.nested.XX.first",
"top.last.XX.nested.XX.second",
"other"]
for path in vars:
print(path, f(x, path))
输出结果:
top.middle.XX.nested 2/3
top.last.XX.nested.XX.first 5/6
top.last.XX.nested.XX.second 4/6
other 1