Javascript 根据特定规则获取自定义数组列表的层次顺序
我想从下面的数组列表中获得层次顺序Javascript 根据特定规则获取自定义数组列表的层次顺序,javascript,jquery,arrays,algorithm,Javascript,Jquery,Arrays,Algorithm,我想从下面的数组列表中获得层次顺序 var data = [ ['','dog'], ['dog','cat'], ['dog','fish'], ['dog','ark'], ['dog','folder'], ['cat','blue'], ['cat','pencil'], ['cat','mouse'], ['fish','stencil'], ['fish','bread'], ['fish','milk'], [
var data = [
['','dog'],
['dog','cat'],
['dog','fish'],
['dog','ark'],
['dog','folder'],
['cat','blue'],
['cat','pencil'],
['cat','mouse'],
['fish','stencil'],
['fish','bread'],
['fish','milk'],
['fish','love'],
['mouse','tv'],
['mouse','oil'],
['mouse','car'],
['milk','dough'],
['milk','butter'],
['car','truck']
];
“计算”的方法是从第一个数组开始
['','dog']
注意:我将0索引(“”)称为“父级”,1索引(“”)称为“子级”
因此,我们希望找到以“dog”为父对象的数组,然后检查这些数组,看看它们的子对象是否有父对象,如果没有,则继续下一个数组。(真希望这有道理)
下面是我的上述数据集的订单结果
var result = ['dog', 'cat', 'blue', 'pencil', 'mouse', 'tv', 'oil', 'car', 'truck', 'fish', 'stencil', 'bread', 'milk', 'dough', 'butter', 'love', 'ark', 'folder'];
我尝试了一些非常糟糕的while循环和.filters()来获取包含子索引作为父索引的数组,但失败了
如果有人能对此提供一些见解或返回最终结果的方法,我将不胜感激,因为我无法继续手动计算。我想,这里是您的算法
function pairsToIndex(pairs) {
return pairs.reduce((index, pair, i, list) => {
let [ parent , child ] = pair;
let parent_exists = index.hasOwnProperty(parent);
let child_exists = index.hasOwnProperty(child);
if(!parent_exists) {
index[parent] = { key: parent , children: [] };
}
if(!child_exists) {
index[child] = { key: child , children: [] };
}
// now, ensure that parent-child relationship is captured
let rel_captured = Boolean( index[parent].children.find((c) => c.key === child) );
if(!rel_captured) {
index[parent].children.push( index[child] );
}
return index;
}, {});
}
let data = [
['','dog'],
['dog','cat'],
['dog','fish'],
['dog','ark'],
['dog','folder'],
['cat','blue'],
['cat','pencil'],
['cat','mouse'],
['fish','stencil'],
['fish','bread'],
['fish','milk'],
['fish','love'],
['mouse','tv'],
['mouse','oil'],
['mouse','car'],
['milk','dough'],
['milk','butter'],
['car','truck']
];
let x = pairsToIndex(data);
console.log(x);
在浏览器的开发控制台中运行该代码。在挖掘对象x
时,您会注意到每个“子对象”的行为就像指向x
的另一个顶级属性的符号链接。实际上,每个“子”都是指向该对象内其他地方的入口。通过引用传递的使用为我们设置了步骤2
键
属性来序列化该对象function listNode(node) {
return Array.prototype.concat.apply( [node.key] , node.children.map(listNode) );
}
let out = listNode(x['']); // choosing the entry point to the hierarchy
console.log(out);
注意,我不得不使用apply
来避免创建一堆嵌套的单元素数组(即使它们的顺序正确)。这可以用\uuu0.flatte
之类的东西来解决,但在这种情况下,对该语言了解多一点就不需要整个库了
还要注意,listNode
在技术上是在层次结构的子树上操作的。我告诉它从“根”节点开始,您建议它在原始数据集中由空字符串标识。但是,您可以要求它通过传递不同的起点来序列化树的子集,例如listNode(x['cat'])
或listNode(x['fish'])
最后,该算法是无限递归的。如果向脚本提供非常大的数据集,浏览器将停止该脚本。其他JS环境(比如nodejs或react native)不会这样做
此时,
out
是一个数组,它按照您希望的顺序列出原始数据中的每个值。我想这里是您的算法
将源数组转换为嵌套对象,该对象使用“按引用传递”有效地关联父对象和子对象
下面是一个ES6实现:
function pairsToIndex(pairs) {
return pairs.reduce((index, pair, i, list) => {
let [ parent , child ] = pair;
let parent_exists = index.hasOwnProperty(parent);
let child_exists = index.hasOwnProperty(child);
if(!parent_exists) {
index[parent] = { key: parent , children: [] };
}
if(!child_exists) {
index[child] = { key: child , children: [] };
}
// now, ensure that parent-child relationship is captured
let rel_captured = Boolean( index[parent].children.find((c) => c.key === child) );
if(!rel_captured) {
index[parent].children.push( index[child] );
}
return index;
}, {});
}
let data = [
['','dog'],
['dog','cat'],
['dog','fish'],
['dog','ark'],
['dog','folder'],
['cat','blue'],
['cat','pencil'],
['cat','mouse'],
['fish','stencil'],
['fish','bread'],
['fish','milk'],
['fish','love'],
['mouse','tv'],
['mouse','oil'],
['mouse','car'],
['milk','dough'],
['milk','butter'],
['car','truck']
];
let x = pairsToIndex(data);
console.log(x);
在浏览器的开发控制台中运行该代码。在挖掘对象x
时,您会注意到每个“子对象”的行为就像指向x
的另一个顶级属性的符号链接。实际上,每个“子”都是指向该对象内其他地方的入口。通过引用传递的使用为我们设置了步骤2
通过以深度优先模式递归遍历该对象并返回每个节点的键
属性来序列化该对象
下面是一个简短的例子:
function listNode(node) {
return Array.prototype.concat.apply( [node.key] , node.children.map(listNode) );
}
let out = listNode(x['']); // choosing the entry point to the hierarchy
console.log(out);
注意,我不得不使用apply
来避免创建一堆嵌套的单元素数组(即使它们的顺序正确)。这可以用\uuu0.flatte
之类的东西来解决,但在这种情况下,对该语言了解多一点就不需要整个库了
还要注意,listNode
在技术上是在层次结构的子树上操作的。我告诉它从“根”节点开始,您建议它在原始数据集中由空字符串标识。但是,您可以要求它通过传递不同的起点来序列化树的子集,例如listNode(x['cat'])
或listNode(x['fish'])
最后,该算法是无限递归的。如果向脚本提供非常大的数据集,浏览器将停止该脚本。其他JS环境(比如nodejs或react native)不会这样做
此时,out
是一个数组,按您希望的顺序列出原始数据
数组中的每个值