我有这些数据:
const items = [
{
_id: 0,
content: 'Item 1 something',
note: 'Some note for item 1'
},
{
_id: 5,
content: 'Item 1.1 something',
note: 'Some note for item 1.1'
},
{
_id: 1,
content: 'Item 2 something',
note: 'Some note for item 2',
subItems: [
{
_id: 2,
parent_id: 1,
content: 'Sub Item 1 something',
subItems: [{
_id: 3,
parent_id: 2,
content: 'Sub Sub Item 4'
}]
}
]
}
];
使用Javascript,我如何导航/插入树中,在任何一点上我都有树中一个项目的_id。
例如,某些案例场景:
如何仅使用_id导航树?
答案 0 :(得分:1)
您可以迭代数组并测试_id
属性是否具有所需值。然后保存节点,父节点或数组的下一个项目。
为了获取父节点,实际的父节点将保存为闭包,并在找到所需的_id
时返回。
所有函数都将subItems
作为数组进行测试,如果是,则执行subItems
上的迭代。
function getNode(array, id) {
var node;
array.some(function iter(a) {
if (a._id === id) {
node = a;
return true;
}
return Array.isArray(a.subItems) && a.subItems.some(iter);
});
return node;
}
function getParent(array, id) {
var parent ;
array.some(function iter(p) {
return function (a) {
if (a._id === id) {
parent = p;
return true;
}
return Array.isArray(a.subItems) && a.subItems.some(iter(a));
};
}(undefined));
return parent;
}
function getNextNode(array, id) {
var node;
array.some(function iter(a, i, aa) {
if (a._id === id) {
node = aa[i + 1];
return true;
}
return Array.isArray(a.subItems) && a.subItems.some(iter);
});
return node;
}
var items = [{ _id: 0, content: 'Item 1 something', note: 'Some note for item 1' }, { _id: 5, content: 'Item 1.1 something', note: 'Some note for item 1.1' }, { _id: 1, content: 'Item 2 something', note: 'Some note for item 2', subItems: [{ _id: 2, parent_id: 1, content: 'Sub Item 1 something', subItems: [{ _id: 3, parent_id: 2, content: 'Sub Sub Item 4' }] }] }];
console.log(getNode(items, 3));
console.log(getParent(items, 2));
console.log(getNextNode(items, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:0)
使用Javascript,我如何导航/插入树中,在任何一点上我都有树中一个项目的_id。
您必须以递归方式遍历树,并跟踪您的位置和所在位置。
JavaScript引用指向一个方向。除了使用_id 1对对象的引用之外什么都没有,你根本没有连接到它所在的数组。 (它甚至可以存在于同一阵列中的多个阵列或多个位置)。
通常,您需要搜索树(递归是您的朋友)并跟踪您关注的成员的索引。
一旦知道了您正在处理的索引,就可以使用splice。
答案 2 :(得分:0)
我已经为这样的问题开发了解决方案。我称之为后视。我的功能看起来:
var backlooker = function(obj) {
for (key in obj) {
if (obj[key]._) {
break;
}
if (obj[key] instanceof Object) {
obj[key]._ = obj;
backlooker(obj[key])
}
}
return obj;
}
您必须先改善对象:
items = backlooker(items);
现在你可以这样做:
a = items[2].subItems[0].subItems[0];
c = a._._._._._._._;
c == items; //true
只有一个问题:如果您的对象中已经有名为_
的密钥,代码将无法正常运行(我认为这种情况非常罕见,但可能)。
答案 3 :(得分:0)
它并不像“导航”那么简单。以下函数将循环遍历对象,并提供可用于实现所需内容的内容..如名称,值,类型,子项数和深度。
还会在下面查看您案例的具体示例
您只需将其称为:loopThrough(items)
并观看您的控制台以获取详细信息。
function loopThrough(obj, depth) {
if (typeof(depth) === "undefined") {
depth = 0; // depth 0 means the "root" of your object
} else {
depth++ // increase depth if exist... depth 1 means a property of an object on depth 0
}
for (keyName in obj) {
let thisObj = obj[keyName] //value of this object
let type = thisObj.constructor.name // type: Array, Object, String, Number or Function...
if (type === "Object" || type === "Array") { // to check if this object "have children" to loop through
let childCount = type === "Object" ? Object.keys(thisObj).length : thisObj.length
console.group(depth + " (" + type + ") " + keyName + " : " + childCount) // starts a collapsable group called: depth, type and key
loopThrough(thisObj, depth) //loop through the child object
console.groupEnd() // closes the group
} else { // doesn't have children (a String, Number or Function)
console.log(depth + " (" + type + ") " + keyName + " : " + thisObj) // types: depth, type key and value
}
}
}
这是一个以_id:3
为目标的示例,在此示例中,我向所需密钥添加了一个兄弟。
loopThrough(items, "_id", 3)
function loopThrough(obj, wantedKey = "", wantedValue = "", depth) {
if (typeof(depth) === "undefined") {
depth = 0;
} else {
depth++
}
for (keyName in obj) {
let thisObj = obj[keyName]
let type = thisObj.constructor.name
if (type === "Object" || type === "Array") {
let childCount = type === "Object" ? Object.keys(thisObj).length : thisObj.length
loopThrough(thisObj, wantedKey, wantedValue, depth)
}
if (keyName === wantedKey && thisObj === wantedValue){
siblings = Object.keys(obj)
console.log('%c Hello!, I am ' + wantedKey +":"+ wantedValue, 'color: green');
console.log('%c I have '+ siblings.length + " siblings: " + siblings.toString(), 'color: green');
console.log("%c adding a new sibling...", 'color: grey')
obj["new_sibling"] = "new_sibling_value" // add a sibling to _id 3
siblings = Object.keys(obj)
console.log('%c now I have '+ siblings.length + " siblings: " + siblings.toString(), 'color: green');
console.log('%c I am at depth ' + depth, 'color: blue');
console.log('%c it should be simple to find a way to get my parent _id at depth ' + (depth - 1) , 'color: blue');ParentID
console.log(JSON.stringify(items, null, 4));
}
}
}
对于您的第二个请求,您必须调整函数以存储所需密钥的深度,并通过调用该函数或创建另一个函数在_id
查找其父depth - 1
对于第三个请求,您可以count++
密钥,一旦找到wantedKey
,您就可以存储计数并再次循环查找count - 1
又名以前的兄弟或count + 1
又名下一个兄弟
正如你所看到的,这不是一项简单的任务,但它完全有可能带来一些创造力,祝你好运。