我有一个如下所示的数据结构,基本上data
是一个包含节点列表的数组,每个节点都可以与parent
节点连接,创建一个类似树的结构。
每个节点都有rotation_relative
属性,这是它的相对旋转。
由于节点可以嵌套在任何级别,我需要根据其父节点为每个节点计算属性rotation_absolute
(我已经为下面树中的每个节点添加了最终结果)。
基本上,叶子的rotation_absolute
等于其父母在正确路径中的总和。
考虑到:
data
数组中的节点可以按任意顺序放置。你能建议任何算法来解决这个问题吗?
A
|_B
| |_F (rotation_absolute = -20)
|
|_C
|_D (rotation_absolute = 20)
|_E (rotation_absolute = 40)
X (rotation_absolute = 20)
|_J (rotation_absolute = 0)
|_Y (rotation_absolute = 40)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<script>
window.app = {
data: [
{
id: 'j',
parent: 'x',
rotation_relative: 20,
rotation_absolute: null
},
{
id: 'y',
parent: 'x',
rotation_relative: 20,
rotation_absolute: null
},
{
id: 'a',
parent: '',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'f',
parent: 'b',
rotation_relative: -20,
rotation_absolute: null
},
{
id: 'b',
parent: 'a',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'e',
parent: 'd',
rotation_relative: 20,
rotation_absolute: null
},
{
id: 'x',
parent: '',
rotation_relative: 20,
rotation_absolute: null
},
{
id: 'c',
parent: 'a',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'd',
parent: 'c',
rotation_relative: 20,
rotation_absolute: null
},
],
start: function () {
// get root
var get1Level = function (parent) {
var nodes1L = this.data.filter(function (item) {
if (item.parent === parent) {
return true;
} else {
return false;
}
}, this);
return nodes1L;
}.bind(this);
var recursion = function (id) {
var nodes = get1Level(id);
nodes.forEach(function (item) {
console.log(item);
recursion.call(this, item.id);
console.log('--');
}, this);
}.bind(this);
var roots = recursion.call(this, '');
}
};
</script>
</head>
注意:
我意识到标题可能真的具有描述性,请随意向我推荐一个更好的标题。谢谢大家。
这是我正在处理的递归示例,但我在添加值部分时遇到了一些问题。
答案 0 :(得分:1)
如果你不介意使用方法,你可以这样做
function rotation_absolute() {
return this.rotation_relative + (this.parentNode ? this.parentNode.rotation_absolute() : 0);
}
var result = {};
var address = {};
window.app.data.forEach(function (e) {
address[e.id] = e;
e.rotation_absolute = rotation_absolute.bind(e);
// see if we have a set of (preceding) nodes with this one as parent
if (result[e.id] instanceof Array) {
result[e.id].forEach(function (c) {
c.parentNode = e;
e[c.id] = c;
});
delete result[e.id];
}
// top level nodes
if (e.parent === "") {
result[e.id] = e;
}
else
{
var parent = address[e.parent]
if (parent !== undefined) {
// add to parent
parent[e.id] = e;
e.parentNode = parent;
}
else {
// add to top level temporary array
result[e.parent] = result[e.parent] || [];
result[e.parent].push(e);
}
}
// don't actually need to do this - I just added it to remove the clutter in the console
delete e.rotation_rotation;
delete e.parent;
})
console.log(result)
console.log(result.a.c.d.e.rotation_absolute())
或者您可以通过构建的层次结构进行递归并使用该方法设置值。
答案 1 :(得分:0)
如果可以限制树的维度,可以尝试嵌套for循环。然后树的每个级别都是一个for循环。树的无限维度并不容易。也许你可以尝试一种递归算法。
答案 2 :(得分:0)
我能够使用递归加上一些额外的逻辑来处理兄弟元素的旋转。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<script>
window.app = {
data: [
{
id: 'a',
parent: 'area',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'b',
parent: 'a',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'c',
parent: 'b',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'd',
parent: 'a',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'e',
parent: 'd',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'f',
parent: 'e',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'g',
parent: 'f',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'area',
parent: '',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'h',
parent: 'area',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'i',
parent: 'h',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'l',
parent: 'h',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'x',
parent: 'area',
rotation_relative: 0,
rotation_absolute: null
},
{
id: 'y',
parent: 'x',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'q',
parent: 'y',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'o',
parent: 'q',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'w',
parent: 'area',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'z',
parent: 'w',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'j',
parent: 'w',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 's',
parent: 'area',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 't',
parent: 's',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'v',
parent: 's',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'm',
parent: 'area',
rotation_relative: -10,
rotation_absolute: null
},
{
id: 'n',
parent: 'm',
rotation_relative: 10,
rotation_absolute: null
},
{
id: 'i',
parent: 'm',
rotation_relative: 10,
rotation_absolute: null
},
],
getById: function (id) {
var result = null;
for (var i = 0, len = this.data.length; i < len; i++) {
var item = this.data[i];
if (item.id === id) {
result = item;
}
}
return result;
},
start: function () {
// get root
var get1Level = function (parent) {
var nodes1L = this.data.filter(function (item) {
if (item.parent === parent) {
return true;
} else {
return false;
}
}, this);
return nodes1L;
}.bind(this);
var increment = 0;
var parent = null;
var recursion = function (id) {
var nodes = get1Level(id);
nodes.forEach(function (item) {
if (!parent) {
parent = item.parent;
}
if (parent && parent === item.parent) {
var targetParent = this.getById(parent);
increment = targetParent.rotation_relative;
increment += item.rotation_relative;
item.rotation_absolute = increment;
}
if (parent && parent !== item.parent) {
parent = item.parent;
var targetParent = this.getById(parent);
increment = targetParent.rotation_absolute ? targetParent.rotation_absolute : 0;
increment += item.rotation_relative;
item.rotation_absolute = increment;
}
console.log(item);
recursion.call(this, item.id);
console.log('---');
}, this);
//increment = 0;
//parent = null;
}.bind(this);
recursion.call(this, 'area');
}
};
</script>
</head>
<body onload="window.app.start();">
</body>
</html>