解
感谢Dave的主要解决方案,下面的答案是解决方案。旁注:如下所示,Dave提供的额外见解或作业对于新手非常有价值。帮助我们伸展。
此代码将遍历现有的JSON树,例如,您想要解析每个值,无论出于何种原因。它不是建造而是走路。在我的情况下,我正在走路并将每个评论解析为更丰富的课程:
var db = [], instance = {}, commentCounter = [];
function hydrateComments(items, parent) {
_.forEach(items, function(item) {
_.has(item, 'descendants') ? hydrateComments(item.descendants, item) : 0;
instance = new CommentModel(_.omit(item,['descendants']));
// other parsers go here, example the counter for each level
// parseCounter(comment);
(parent['children'] = (parent['children'] || [])) && item.depth > 0 ?
parent.children.push(instance) :
parent.push(instance);
});
}
hydrateComments(comments, storeComments);
ANGULAR DIRECTIVE
对于那些使用此代码构建树的人,我包含一个可以帮助您使用上述树构建树的指令。
请注意我删除了很多我自己的代码并且没有对此进行测试,但我知道我花了很多时间试图找到树和模板,所以希望这对你有所帮助。
buildTree.$inject = [];
function buildTree() {
link.$inject = ["scope", "elem", "attrs"];
function link(scope, elem, attrs) {
}
CommentController.$inject = ["$scope"];
function CommentController($scope) {
$scope.$watchCollection(function () {
return CommentDataService.getComments();
},
function (newComments, oldValue) {
if (newComments) {
$scope.comments.model = newComments;
}
}, true);
}
return {
restrict: "A",
scope: {
parent: "=cmoParent"
},
template: [
"<div>",
"<script type='text/ng-template'",
"id=" + '"' + "{[{ parent.app_id }]}" + '"' + " >",
"<div class='comment-post-column--content'>",
"<div cmo-comment-post",
"post-article=parent",
"post-comment=comment>",
"</div>",
"</div>",
"<ul ng-if='comment.children'>",
"<li class='comment-post-column--content'",
"ng-include=",
"'" + '"' + "{[{ parent.app_id }]}" + '"' + "'",
"ng-repeat='comment in comment.children",
"track by comment.app_id'>",
"</li>",
"</ul>",
"</script>",
"<ul class='conversation__timeline'>",
"<li class='conversation__post-container'",
"ng-include=",
"'" + '"' + "{[{ parent.app_id }]}" + '"' + "'",
"ng-repeat='comment in comments.model[parent.app_id]",
"track by comment.app_id'>",
"</li>",
"<ul>",
"</div>"
].join(' '),
controller: CommentController,
link: link
}
}
奖金
我也发现了一个很棒的技巧。如何使用一行代码初始化和填充数组。在我的情况下,我有一个计数器方法,将计算我使用提示的每个级别的每个评论:
parseCounter: function(comment) {
var depth = comment.depth;
(commentCounter[depth] = (commentCounter[depth] || [])) ? commentCounter[depth]++ : 0;
},
原始问题
下面的代码解析多级对象数组,目的是将所有对象解析为“CommentModel”
的实例,虽然在这个例子中简单的是更丰富的对象类,但为了简洁起见,我简化了对象/类。
现有堆叠交换内容:
关于设置多维数组的内容很多,几乎所有内容都显示了例如:
var item[‘level1’][‘level2’] = ‘value’;
或
var item = [];
var item['level1'] = [];
或
var item = new Array([]) // and or objects
但是,没有这样的例子:
var item[‘level1’].push(object)
问题:
有没有办法初始化2级深度多维数组,同时在一行代码中推送它?
1.1即在parent[‘children’]
下面的例子中,我被迫检查它是否存在,如果没有设置它。如果我尝试parent[‘children’].push(instance)
,我显然会推动未定义的异常。是否有单行或更好的方法来检查财产是否存在,如果不存在?我显然不能在每次迭代时在父级上设置一个空数组,即parent ['children'] = [];和父母['children'] =价值不会工作
是否可以将初始化和验证移动到
CommentModel实例?我问我试图
CommentModel.prototype['children'] = []
;但后来所有的孩子('后代')
对象被添加到名为的proto属性中的每个对象
“孩子们”,这很有意义。
方面的问题 - 我认为我的树迭代代码function hydrateComments(items, parent)
很简洁但是我能做些什么来进一步简化lodash和/或angular?我见过的大多数例子都是冗长的,并没有真正走过树枝。
PLUNKER&amp;代码
https://plnkr.co/edit/iXnezOplN4hNez14r5Tt?p=preview
var comments = [
{
id: 1,
depth: 0,
subject: 'Subject one'
},
{
id: 2,
depth: 0,
subject: 'Subject two',
descendants: [
{
id: 3,
depth: 1,
subject: 'Subject two dot one'
},
{
id: 4,
depth: 1,
subject: 'Subject two dot two'
}
]
},
{
id: 5,
depth: 0,
subject: 'Subject three',
descendants: [
{
id: 6,
depth: 1,
subject: 'Subject three dot one'
},
{
id: 7,
depth: 1,
subject: 'Subject three dot two',
descendants: [
{
id: 8,
depth: 2,
subject: 'Subject three dot two dot one'
},
{
id: 9,
depth: 2,
subject: 'Subject three dot two dot two'
}
]
}
]
}
];
function hydrateComments(items, parent) {
_.forEach(items, function (item) {
// create instance of CommentModel form comment. Simply example
var instance = new CommentModel(item);
// if we have descendants then injec the descendants array along with the
// current comment object as we will use the instance as the "relative parent"
if (_.has(instance, 'descendants')) {
hydrateComments(instance.descendants, instance);
}
// we check is parent has a property of children, if not, we set it
// NOTE : 3 lines of code ? is there a more concise approach
if (!_.has(parent, 'children')) {
parent['children'] = [];
}
// if depth id greater than 0, we push all instances of CommentModel of that depth to the
// parent object property 'children'. If depth is 0, we push to root of array
if (item.depth > 0) {
parent.children.push(instance);
} else {
parent.push(instance);
}
})
}
// simple example, but lets assume much richer class / object
function CommentModel(comment) {
this.id = comment.id;
this.depth = comment.depth;
this.subject = comment.subject;
this.descendants = comment.descendants;
}
var output = [];
// init - pass in data and the root array i.e. output
hydrateComments(comments, output);
// Tada - a hydrated multi-level array
console.log('Iteration output for comments : ', output)
答案 0 :(得分:1)
要在单个语句中初始化数组,您可以执行以下操作
方法1 :(初始化
parent['children']
)ANS到Q#1
排行榜#1:https://plnkr.co/edit/lmkq8mUWaVrclUY2CoMt?p=preview
function hydrateComments(items, parent) {
_.forEach(items, function(item) {
// create instance of CommentModel form comment. Simply example
var instance = new CommentModel(item);
// if we have descendants then injec the descendants array along with the
// current comment object as we will use the instance as the "relative parent"
_.has(instance, 'descendants') ? hydrateComments(instance.descendants, instance) : 0;
//Less eff. and less readable then method #2
(parent['children'] = (parent['children'] || [])) && item.depth > 0 ?
parent.children.push(instance) :
parent.push(instance);
});
}
方法2 :(初始化
parent['children']
)ANS到Q#2 - 我更喜欢这个。
#2的引人注目:https://plnkr.co/edit/zBsF5o9JMb6ETHKOv8eE?p=preview
function CommentModel(comment) {
this.id = comment.id;
this.depth = comment.depth;
this.subject = comment.subject;
this.descendants = comment.descendants;
//Initialise children in constructer itself! :)
this.children = [];
}
function hydrateComments(items, parent) {
_.forEach(items, function(item) {
// create instance of CommentModel form comment. Simply example
var instance = new CommentModel(item);
// if we have descendants then injec the descendants array along with the
// current comment object as we will use the instance as the "relative parent"
_.has(instance, 'descendants') ? hydrateComments(instance.descendants, instance) : 0;
item.depth > 0 ? parent.children.push(instance) : parent.push(instance);
});
}
ANS到Q#3
我觉得你的代码还可以。但如果深度增加太多,您可能会遇到stackoverflow
。使用trampolines通过递归解决此问题。但如果你确定深度不是
我想在上面的文章中引用几行:
此图表未显示的是30,000递归之后 调用浏览器挂起;到了它必须被强行关闭的程度 下。与此同时,蹦床继续蹦蹦跳跳数百人 成千上万的调用。这个数字没有实际限制 蹦床可以弹跳。
但是只使用trampoline
,你知道深度足以导致堆栈溢出。
希望这有帮助!