您可以使用字典来表示您的wifi网络,然后简单地使用递归查找问题根源:
d = {1: [2, 3, 4], 2: ['A', 'B', 'C'], 3: None, 4: ['D', 'E']}
def search(_d, a):
return (_d and a in _d) or (_d and any(search(d.get(i, []), a) for i in _d))
down = ['D', 'E', 4]
r = [a for i, a in enumerate(down) if all(search(d.get(a, []), j) for j in down[:i]+down[i+1:])]
输出:
[4]
编辑:如果中断的发起者可能不在 down 中,您可以简单地展平结构并再次运行搜索:
down = ['D', 'E']
_r = {a for c, _d in d.items() for a in [c, *([] if _d is None else _d)]}
result = [i for i in _r if all(search(d.get(i, []), j) for j in down)]
输出:
[1, 4]
输出为[1, 4],因为4 是1 的子节点,而4 包含受影响的子节点。如何区分这些结果取决于您自己,因为两者都可能有效,即 1 可能已关闭或 4 可能已关闭。
根据您的最新输入,我认为最好的方法是创建一个新字典,为集合中的每个父级记录所有子节点。
from collections import defaultdict
def get_paths(_d, c = []):
for i in _d:
if d.get(i) is None:
yield c+[i]
else:
yield from get_paths(d[i], c+[i, *([] if d[i] is None else d[i])])
result = defaultdict(list)
for a, b in d.items():
result[a].extend(([] if b is None else get_paths(b)))
result = {a:{i for c in b for i in c} for a, b in result.items()}
现在,获取下节点:
def get_down(down):
_r, _n = zip(*[[a, b] for a, b in result.items() if b and all(i in down for i in b)])
n = {i for b in _n for i in b}
return list(_r) + [i for i in down if i not in result and i not in n]
final_results = [get_down(i) for i in [['D', 'E','C'], ['D', 'E']]]
输出:
[[4, 'C'], [4]]