我有一个高度嵌套的多维数组,类似于下面的数组。为简单起见,我用json格式表达它:
[
{
"Object": "Car",
"Child": [
{
"Object": "Toyota",
"Child": [
{
"Object": "Prius"
},
{
"Object": "Yaris"
}
]
},
{
"Object": "Honda",
"Child": [
{
"Object": "Accord"
},
{
"Object": "Civic",
"Child": [
{
"Object": "Sedan"
},
{
"Object": "Coupe"
}
]
}
]
}
]
}
]
如何确定对象是否是另一个对象的直系后代?
例如,“轿车”是“思域”,“本田”和“汽车”的直系后代;但不是“Coupe”,“Accord”,“Toyota”,“Prius”或“Yaris”的直系后裔。
我想做这样的事情:
function Lineal_Descendant(A,B){
/*do something*/
}
Lineal_Descendant("Sedan","Civic") /*return true*/
Lineal_Descendant("Sedan","Toyota") /*return false*/
Lineal_Descendant("Prius","Honda") /*return false*/
Lineal_Descendant("Yaris","Car") /*return true*/
答案 0 :(得分:2)
好的,我会试一试:http://jsfiddle.net/nrabinowitz/UJrhK/
function Lineal_Descendant(child, parent) {
// search in an array of objects
function walk(array, search) {
for (var x=0, found; x<array.length; x++) {
found = visit(array[x], search);
if (found) return found;
}
return false;
}
// search an object and its children
function visit(obj, search) {
// found search
return obj.Object === search ? obj :
// not found, but has children
obj.Child ? walk(obj.Child, search) :
// no children
false;
}
// find parent
parent = walk(data, parent);
// find child, converting to boolean
if (parent) return !!walk(parent.Child || [], child);
}
这可能是一种更优雅的方式,但这会奏效。请注意,您的数据结构中没有任何内容可以强制使用唯一名称,因此如果您在同一级别有两个项目具有相同的Object
值,则搜索可能会返回意外结果。
答案 1 :(得分:2)
这是一种怪异的黑客攻击,但你可以使用浏览器DOM模型来做这些事情。将您的数据结构的某种'预先缓存'添加到DOM中并使用querySelectorAll
或类似的东西遍历它(jQuery或其他)
参见jsFiddle - http://jsfiddle.net/SxCD6/2/
答案 2 :(得分:1)
这是一个小巧的,自包含的递归函数,可以完成你想要的任务:
function linearDescendant(list, search, ancestor, _parent) {
var i, item, found = false;
for (i=0; i<list.length; i++) {
item = list[i];
item._parent = _parent;
if (item.Object == search) {
while (item._parent && item.Object != ancestor) {
item = item._parent;
}
found = item.Object == ancestor;
} else if (item.Child) {
found = linearDescendant(item.Child, search, ancestor, item);
}
if (found) break;
}
return found;
}
称之为:
linearDescendant(yourArray, "Sedan", "Civic") // true
linearDescendant(yourArray, "Sedan", "Toyota") // false
linearDescendant(yourArray, "Prius", "Honda") // false
linearDescendant(yourArray, "Yaris", "Car") // true
请注意,该函数会在每个嵌套对象中创建一个_parent
属性。一旦找到搜索到的对象,就必须进行祖先检查。
答案 3 :(得分:1)
我最终使用Modified Preorder Tree Traversal的概念。基本上,我使用一个自包含的递归函数循环遍历json对象;并为每个对象分配“左”和“右”值。一旦修改了整个json对象并包含“left”和“right”值,我会比较对象A和B中的“left”和“right”值,看它是否是一个直系后代。
例如,如果对象A是B的直线后代,则A中的“左”值将大于B中的“左”值,而A中的“右”将小于B中的“右”。 / p>
代码:
var data = [{"Object":"Car","Child":[{"Object":"Toyota","Child":[{"Object":"Prius"},{"Object":"Yaris"}]},{"Object":"Honda","Child":[{"Object":"Accord"},{"Object":"Civic","Child":[{"Object":"Sedan"},{"Object":"Coupe"}]}]}]}];
alert(Lineal_Descendant(data,'Sedan','Civic')); //true
alert(Lineal_Descendant(data,'Sedan','Toyota')); //false
alert(Lineal_Descendant(data,'Prius','Honda')); //false
alert(Lineal_Descendant(data,'Yaris','Car')); //true
function Lineal_Descendant(data, A, B){
var i=1, //value to be assigned to "left" or "right" in modified preorder tree traversal
k=0, //value to be assgined to entry index
aIndex, //entry index value for object A
bIndex, //entry index value for object B
entry = new Array(), //entry element
mpttObj = mptt(data); //modified preorder tree traversal recursive function. Assign "left" and "right" value.
function mptt(obj) {
for (var f=0, n=obj.length; f<n; f++) {
if(obj[f].Object==A) aIndex=k;
if(obj[f].Object==B) bIndex=k;
obj[f].index=k;
entry[obj[f].index] = {left:i, right:-1};
obj[f].left=i;
//alert(obj[f].Object+','+obj[f].index+','+ obj[f].left);
k++;
i++;
if (obj[f].Child) mptt(obj[f].Child);
entry[obj[f].index].right = i;
//alert(obj[f].Object+','+obj[f].index+','+entry[obj[f].index].right);
obj[f].right=i;
i++;
}
return obj;
}
if(entry[aIndex].left>entry[bIndex].left && entry[aIndex].right<entry[bIndex].right) return true;
else return false;
}
答案 4 :(得分:1)
首先,
"Object"
作为Object
上的密钥。实际上覆盖本机javascript Object
,这只是一个小错误,它会释放javascript apocalypse。我建议使用name
作为替代方案。
其次,这可以通过一个非常简单的递归函数来解决:
var find = function(obj, search){
// return this object if it matches
if(obj.name === search)
return obj;
// false if it has no children
if(!obj.hasOwnProperty('Child'))
return false;
for(var i=0,u=obj.Child.length;i<u;i++){
// recursively check each child
var foundRecursively = find(obj.Child[i], search);
if(foundRecursively) // match found! return up the chain
return foundRecursively;
}
// no match, return up the chain
return false;
};
var Lineal_Descendant = function(A,B){
// find the B (the parent) in data, then find A in B.
// Negate any object to a boolean and return.
return !!find(find(data[0],B),A);
};
Lineal_Descendant("Sedan","Civic") // true
Lineal_Descendant("Sedan","Toyota") // false
Lineal_Descendant("Prius","Honda") // false
Lineal_Descendant("Yaris","Car") // true
此解决方案要求数据为具有1个根对象的数组(如示例数据中的OP所示)。也就是说,它很容易适应接受一系列根源开始。