在javascript中遍历递归关系矩阵
有很多元素(用复选框表示)具有一些不同的关系。例如:在javascript中遍历递归关系矩阵,javascript,recursion,matrix,checkbox,Javascript,Recursion,Matrix,Checkbox,有很多元素(用复选框表示)具有一些不同的关系。例如: A需要B A需要C A不能与D结合 B不能与E结合 D需要E C需要F F不能与G结合 S不能与B结合 T不能与D结合 美国需要美国 编辑:答案中出现了3个问题,我想在这里定义这些问题: 问:什么是默认、禁止或需要的?A:没有。如果 两个元素之间没有关系,它们可以独立工作 (只要与一个公共元素没有关系 否则) 问:如果A禁止B,B是否会自动禁止A?A:是的。 猫(A)说,你不能和狗(B)在一起。即使狗 不关心猫,你不能把它们结合起来,因
- A需要B
- A需要C
- A不能与D结合
- B不能与E结合
- D需要E
- C需要F
- F不能与G结合
- S不能与B结合
- T不能与D结合
- 美国需要美国
- 问:什么是默认、禁止或需要的?A:没有。如果 两个元素之间没有关系,它们可以独立工作 (只要与一个公共元素没有关系 否则)
- 问:如果A禁止B,B是否会自动禁止A?A:是的。 猫(A)说,你不能和狗(B)在一起。即使狗 不关心猫,你不能把它们结合起来,因为猫 我不会喜欢的
- 问:如果A需要B,B是否自动需要A?不,如果你愿意的话 要读取stackoverflow(A),您需要浏览器(B)。但是如果你想 要使用浏览器(B),您不需要stackoverflow(A)
第二个问题是:如果用户再次禁用复选框A,则需要再次检查所有关系-对于所有仍处于活动状态的复选框也是如此。编辑:要求已细化 简单的递归不行
var relations = {
'A': {
'B': 'needed',
'C': 'needed',
'D': 'prohibited'
},
'B': {
'E': 'prohibited'
},
'D': {
'E': 'needed'
},
'E':{/* added for simplicity */},
'C': {
'F': 'needed'
},
'F': {
'G': 'prohibited'
}
};
var tmp = {};
function checkRelations(start) {
for (var relation in relations[start]) {
if (!tmp.hasOwnProperty(relation)) {
tmp[relation] = {};
}
if (relations[start][relation] === 'needed') {
tmp[relation][start] = 'needed';
} else if (relations[start][relation] === 'prohibited') {
tmp[relation][start] = 'prohibited';
}
checkRelations(relation);
}
}
function run(obj) {
for (var e in obj) {
checkRelations(e);
}
}
run(relations);
JSON.stringify(tmp);
将得到以下结果:
{
'B': {
'A': 'needed',
'S': 'prohibited'
},
'E': {
'B': 'prohibited',
'D': 'needed'
},
'C': {
'A': 'needed'
},
'F': {
'C': 'needed'
},
'G': {
'F': 'prohibited'
},
'D': {
'A': 'prohibited',
'T': 'prohibited'
},
'S': {
'U': 'needed'
}
}
正如您从第一个条目B
中看到的:您的数据库定义不足。每个未定义的元素会发生什么情况?如果未定义某项内容,默认设置是什么?是禁止的还是“需要的”?如果'A'
需要'B'
这是否意味着'B'
需要'A'
一旦定义了,您就可以(自动)填充数据库的第一层,并在此基础上构建一个树(dito自动),如果您需要,可以通过花费大量内存(O(n^2))来确保大量处理(O(n^2))
所有这些都是在假设整个事物是一致的,并且在任何地方都没有无限循环的情况下发生的
默认值设置为'meh'
时,第一轮为
function checkRelations(start) {
for (var relation in relations[start]) {
if (!relations.hasOwnProperty(relation)) {
relations[relation] = {
};
}
if (relations[start][relation] === 'needed') {
relations[relation][start] = 'meh';
} else if (relations[start][relation] === 'prohibited') {
relations[relation][start] = 'prohibited';
}
for (var r in relations) {
if (!relations[relation].hasOwnProperty(r) && relation != r) {
relations[relation][r] = 'meh';
}
}
}
}
function run(obj) {
for (var e in obj) {
// fill database up
checkRelations(e);
}
}
run(relations);
JSON.stringify(relations)
{
'A': {
'B': 'needed',
'C': 'needed',
'D': 'prohibited',
'E': 'meh',
'F': 'meh',
'S': 'meh',
'T': 'meh',
'U': 'meh',
'G': 'meh'
},
'B': {
'E': 'prohibited',
'A': 'meh',
'D': 'meh',
'C': 'meh',
'F': 'meh',
'S': 'prohibited',
'T': 'meh',
'U': 'meh',
'G': 'meh'
},
'E': {
'B': 'prohibited',
'A': 'meh',
'D': 'meh',
'C': 'meh',
'F': 'meh',
'S': 'meh',
'T': 'meh',
'U': 'meh',
'G': 'meh'
},
'D': {
'E': 'needed',
'A': 'prohibited',
'B': 'meh',
'C': 'meh',
'F': 'meh',
'S': 'meh',
'T': 'prohibited',
'U': 'meh',
'G': 'meh'
},
'C': {
'F': 'needed',
'A': 'meh',
'B': 'meh',
'E': 'meh',
'D': 'meh',
'S': 'meh',
'T': 'meh',
'U': 'meh',
'G': 'meh'
},
'F': {
'G': 'prohibited',
'A': 'meh',
'B': 'meh',
'E': 'meh',
'D': 'meh',
'C': 'meh',
'S': 'meh',
'T': 'meh',
'U': 'meh'
},
'S': {
'B': 'prohibited',
'A': 'meh',
'E': 'meh',
'D': 'meh',
'C': 'meh',
'F': 'meh',
'T': 'meh',
'U': 'meh',
'G': 'meh'
},
'T': {
'D': 'prohibited',
'A': 'meh',
'B': 'meh',
'E': 'meh',
'C': 'meh',
'F': 'meh',
'S': 'meh',
'U': 'meh',
'G': 'meh'
},
'U': {
'S': 'needed',
'A': 'meh',
'B': 'meh',
'E': 'meh',
'D': 'meh',
'C': 'meh',
'F': 'meh',
'T': 'meh',
'G': 'meh'
},
'G': {
'F': 'prohibited',
'A': 'meh',
'B': 'meh',
'E': 'meh',
'D': 'meh',
'C': 'meh',
'S': 'meh',
'T': 'meh',
'U': 'meh'
}
}
那已经很贵了。您可以展开树,但我会停在这里,按照路径'needed'
动态构建树。您应该能够使用第一个递归方法来执行此操作,如果您发现一个“需要”
”(如果默认值为“禁止”
)
例如:
A - B(n) - C(n) - D(p)
| |
E(p) F(n)
|| |
S(p) G(p)
(一根是树枝,两根是叶子)
当然,根据默认值处理'meh'
部分。如果默认值为'panbited'
,则您甚至可以完全跳过'meh'
条目的构造,而只剩下'needed'
条目
剩下的就是
{
'A': {
'B': 'needed',
'C': 'needed'
},
'B': {
'nothing':0
},
'E': {
'nothing':0
},
'D': {
'E': 'needed'
},
'C': {
'F': 'needed'
},
'F': {
'nothing':0
},
'S': {
'nothing':0
},
'T': {
'nothing':0
},
'U': {
'S': 'needed'
},
'G': {
'nothing':0
}
}
并降至最低限度:
{
'A': {
'B': 'needed',
'C': 'needed'
}
'D': {
'E': 'needed'
},
'C': {
'F': 'needed'
}
'U': {
'S': 'needed'
}
}
完整算法:如果需要,将所有条目设置为“禁止”
,并遍历上面列出的由以下小脚本生成的小数据库
function checkRelations(start) {
for (var relation in relations[start]) {
if (relations[start][relation] === 'prohibited') {
delete relations[start][relation];
}
}
}
function isEmpty(obj) {
for(var p in obj) {
if(obj.hasOwnProperty(p)){
return false;
}
}
return true;
}
function run(obj) {
for (var e in obj) {
// fill database up
checkRelations(e);
// delete empty entries
if(isEmpty(relations[e])){
delete relations[e];
}
}
}
遍历最后一个的函数:
function followPath(start){
for (var relation in reduced[start]) {
console.log(relation + " is needed")
if (reduced.hasOwnProperty(relation)) {
console.log( relation + " is needed, follow path")
followPath(relation);
}
}
}
啊,太晚了。再次;-)
但至少比我一开始想象的要简单一些(如果我正确计算循环的话,速度更快)。您作为示例给出的关系可以表示为带标记边的有向图:
在上面的图像中,边的颜色表示边的标签或标记:
绿色:需要
红色:禁止
边上的点代表一个方向
function checkRelations(start) {
for (var relation in relations[start]) {
if (relations[start][relation] === 'prohibited') {
delete relations[start][relation];
}
}
}
function isEmpty(obj) {
for(var p in obj) {
if(obj.hasOwnProperty(p)){
return false;
}
}
return true;
}
function run(obj) {
for (var e in obj) {
// fill database up
checkRelations(e);
// delete empty entries
if(isEmpty(relations[e])){
delete relations[e];
}
}
}
function followPath(start){
for (var relation in reduced[start]) {
console.log(relation + " is needed")
if (reduced.hasOwnProperty(relation)) {
console.log( relation + " is needed, follow path")
followPath(relation);
}
}
var graph = { v: [], e: [] } // v: vertices or nodes, e: edges
var vertex = {
name: "A",
el : someElement
};
var edge = {
s: sourceVertex,
d: destinationVertex,
tag: "n" // the tag will define the type of relation
// again you can use strings: 'n' - `needs` and 'p' - `prohibits`
// or whatever type you like
};