简体   繁体   English

获取父元素及其所有子元素的数组

[英]get array of parent and all of its child

suppose I have this kind of data... 假设我有这种数据......

data = [{
    "_id" : "1",
    "parentId" : "thisPostId",
    "topLevelId" : "1",
    "text" : "<p>comment</p>",
},
{
    "_id" : "2",
    "parentId" : "1",
    "topLevelId" : "1",
    "text" : "<p>reply to comment</p>",
},
{
    "_id" : "3",
    "parentId" : "2",
    "topLevelId" : "1",
    "text" : "<p>reply to reply to comment</p>",
},
{
    "_id" : "4",
    "parentId" : "3",
    "topLevelId" : "1",
    "text" : "<p>reply to reply to reply to comment</p>",
}]

I need to remove a comment and all of its child... 我需要删除评论及其所有孩子......

if comment to remove is _id:1 ,, then I need an array of ["1","2","3","4"] ,,, then i can run Coll.remove({_id:{$in:["1","2","3","4"]}}, callback); 如果要删除的注释是_id:1 ,,那么我需要一个["1","2","3","4"]数组,然后我可以运行Coll.remove({_id:{$in:["1","2","3","4"]}}, callback);

if comment to remove is _id:2 ,, then I need an array of ["2","3","4"] 如果要删除的注释是_id:2 ,,那么我需要一个["2","3","4"]数组["2","3","4"]

if comment to remove is _id:3 ,, then I need an array of ["3","4"] 如果要删除的注释是_id:3 ,,那么我需要一个["3","4"]的数组

if comment to remove is _id:4 ,, then I need an array of ["4"] 如果要删除的注释是_id:4 ,,那么我需要一个["4"]的数组

I tried this (with no idea)... 我试过这个(不知道)......

_.forEach(data, function(value, key){
    _.pluck(_.where(key, { "parentId" : "2" }), '_id');
});

and not working... 并没有工作......

any help with javascript/lodash/underscore will be appreciated,,, 任何有关javascript / lodash / underscore的帮助将不胜感激,,,

thank You... 谢谢...

Here is another interpretation using the native Array.prototype.reduce method to only add the child elements to the returned array. 下面是使用本机Array.prototype.reduce方法的另一种解释,只将子元素添加到返回的数组中。

edit, didn't read question properly, this will now return the current id and all children. 编辑,没有正确读取问题,现在将返回当前的id和所有孩子。

 var data = [{ "_id" : "1", "parentId" : "thisPostId", "topLevelId" : "1", "text" : "<p>comment</p>", }, { "_id" : "2", "parentId" : "1", "topLevelId" : "1", "text" : "<p>reply to comment</p>", }, { "_id" : "3", "parentId" : "2", "topLevelId" : "1", "text" : "<p>reply to reply to comment</p>", }, { "_id" : "4", "parentId" : "3", "topLevelId" : "1", "text" : "<p>reply to reply to reply to comment</p>", }]; function getChildIds( arr, id ){ var parentFound = false; return arr.reduce(function( ret, item ){ if( parentFound === false && item._id == id ){ parentFound = true; } if( parentFound ) { ret = ret.concat( item._id ); } return ret; }, []); } console.log( getChildIds(data, '1') ); console.log( getChildIds(data, '2') ); console.log( getChildIds(data, '3') ); console.log( getChildIds(data, '4') ); 
 <script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script> 

any order, not sure why it's necessary thought. 任何订单,不知道为什么有必要考虑。

 var data = [{ "_id": "2", "parentId": "1", "topLevelId": "1", "text": "<p>reply to comment</p>", }, { "_id": "1", "parentId": "thisPostId", "topLevelId": "1", "text": "<p>comment</p>", }, { "_id": "4", "parentId": "3", "topLevelId": "1", "text": "<p>reply to reply to reply to comment</p>", }, { "_id": "3", "parentId": "2", "topLevelId": "1", "text": "<p>reply to reply to comment</p>", }]; function getChildIdsInAnyOrder(arr, id) { return arr.reduce(function(ret, item) { if ( parseInt(item._id) >= parseInt(id) ) { ret = ret.concat(item._id); } return ret; }, []); } console.log(getChildIdsInAnyOrder(data, '1')); console.log(getChildIdsInAnyOrder(data, '2')); console.log(getChildIdsInAnyOrder(data, '3')); console.log(getChildIdsInAnyOrder(data, '4')); 
 <script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script> 

First you need a function to get the topLevelId from the object with that matches the search id: 首先,您需要一个函数来从对象获取topLevelId ,并匹配搜索ID:

function getTLID(searchId) {
  return data.filter(function(el) {
    return el._id === searchId;
  })[0].topLevelId;
}

With reduce : add the _id of each object to the returned array that has that search id and either have the search id or have a parentId greater or equal to the search id, the use map to grab the _id s. 使用reduce :将每个对象的_id添加到具有该搜索ID的返回数组, 并且具有搜索ID 或者具有大于或等于搜索ID的parentId ,使用map来获取_id s。

function getIdArray(searchId) {
  var tlid = getTLID(searchId);
  return data.reduce(function (p, c) {
    var matchSearchId = +c.parentId >= +searchId || c._id === searchId;
    if (c.topLevelId === tlid && matchSearchId) p.push(c._id);
    return p;
  }, []).sort();
}

getIdArray('1') // [ "1", "2", "3", "4" ]
getIdArray('2') // [ "2", "3", "4" ]
getIdArray('3') // [ "3", "4" ]
getIdArray('4') // [ "4" ]

DEMO DEMO

If you don't like reduce , perhaps using filter and map . 如果您不喜欢reduce ,可能使用filtermap

function getIdArray(searchId) {
  var tlid = getTLID(searchId);
  return data.filter(function(el) {
    var matchSearchId = +el.parentId >= +searchId || el._id === searchId;
    return el.topLevelId === tlid && matchSearchId;
  }).map(function(el) {
    return el._id;
  }).sort();
}

DEMO DEMO

This is a rather lengthy one using recursion, 这是一个使用递归的相当冗长的,

function getIDs(arr, id) {
arr = arr || data;
var ret = [];
for (var i = 0; i < arr.length; i++) {
    var item = arr[i];
    if (item.parentId == id || item._id == id) {
        if (ret.indexOf(item._id) < 0) {
            ret.push(item._id);
            var newret = []
            for (var x = 0; x < arr.length; x++) {
                if (x != i) newret.push(arr[x]);
            }
            var children = getIDs(newret, item._id);
            if (children.length > 0) {
                for (var j = 0; j < children.length; j++) {
                    if (!(ret.indexOf(children[j]) >= 0)) { ret.push(children[j]); }
                }
            }
        }

    }
}
return ret;

} }

It works by getting the id of the desired parent, then getting the ids of its children, and its children's children, it could do this all day ... 它的工作原理是获取所需父级的id,然后获取其子级的id及其子级的子级,它可以整天执行此操作...

First of all, you need to get the index of the item having mentioned _id , If item exists in the array then you can use array.splice to remove the n elements from mentioned index. 首先,你需要获得已提到_id的项的索引,如果array存在item,那么你可以使用array.splice从提到的索引中删除n元素。 To get items from the deleted node, deepcopy of the array is stored in temperory variable. 为了充分利用的项目deleted节点, deepcopy的阵列的存储在temperory变量。

The splice() method changes the content of an array by removing existing elements and/or adding new elements. splice()方法通过删除现有元素和/或添加新元素来更改数组的内容。

You can calculate the delete count using data.length - index 您可以使用data.length - index计算删除计数

 var data = [{ "_id": "1", "parentId": "thisPostId", "topLevelId": "1", "text": "<p>comment</p>", }, { "_id": "2", "parentId": "1", "topLevelId": "1", "text": "<p>reply to comment</p>", }, { "_id": "3", "parentId": "2", "topLevelId": "1", "text": "<p>reply to reply to comment</p>", }, { "_id": "4", "parentId": "3", "topLevelId": "1", "text": "<p>reply to reply to reply to comment</p>", }]; var getIndex = function(_id) { for (var i = 0; i < data.length; i++) { if (data[i]._id == _id) { return i; } } }; function deepCopy(obj) { if (null == obj || "object" != typeof obj) return obj; var copy = obj.constructor(); for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; } return copy; } var _id = 1; var index = getIndex(_id); var _temp = deepCopy(data); var removedData = data.splice(index, 1); alert(removedData); if (typeof index !== 'undefined') { var neededData = _temp.splice(index, (_temp.length - index)); alert(neededData); } 

Fiddle here 在这里小提琴

TRY THIS: 试试这个:

HTML: HTML:

<input type="text" id="Txt" />

<button type="button" onclick="check();">
Check
</button>

JS: JS:

data = [{
    "_id" : "1",
    "parentId" : "thisPostId",
    "topLevelId" : "1",
    "text" : "<p>comment</p>",
},
{
    "_id" : "2",
    "parentId" : "1",
    "topLevelId" : "1",
    "text" : "<p>reply to comment</p>",
},
{
    "_id" : "3",
    "parentId" : "2",
    "topLevelId" : "1",
    "text" : "<p>reply to reply to comment</p>",
},
{
    "_id" : "4",
    "parentId" : "3",
    "topLevelId" : "1",
    "text" : "<p>reply to reply to reply to comment</p>",
}];


function check() {
    getIds(document.getElementById("Txt").value);
}

function getIds(id) {
    var allow = false,
        result = [];

    for (var i = 0; i < data.length; i++) {
        if (data[i]._id == id) {
            allow = true;
        }
        if (allow) {
            result.push(data[i]._id)
        }
    }

    retrun result;
}

You can try something like this: 你可以尝试这样的事情:

Code

JSFiddle 的jsfiddle

 var data = [{ "_id": "1", "parentId": "thisPostId", "topLevelId": "1", "text": "<p>comment</p>", }, { "_id": "2", "parentId": "1", "topLevelId": "1", "text": "<p>reply to comment</p>", }, { "_id": "3", "parentId": "2", "topLevelId": "1", "text": "<p>reply to reply to comment</p>", }, { "_id": "4", "parentId": "3", "topLevelId": "1", "text": "<p>reply to reply to reply to comment</p>", }]; function getDependentList(id) { var retList = []; data.forEach(function(item) { if (item.parentId == id) retList.push(item["_id"]); }); if (retList.length > 0) { retList.forEach(function(item) { retList = retList.concat(getDependentList(item).slice(0)); }); } return retList; } function getRemoveList() { var id = document.getElementById("txtInput").value; var removeList = []; removeList.push(id); removeList = removeList.concat(getDependentList(id)) console.log(removeList); } 
 <input type="text" id="txtInput"> <button onclick="getRemoveList()">get Lists</button> 

This is a proposal with a temporary object and a recursive call for the ids. 这是一个带有临时对象和id的递归调用的提议。

The temporary object o contains all ids and their childrens 临时对象o包含所有id及其子级

{
    "1": ["2"],
    "2": ["3"],
    "3": ["4"],
    "thisPostId": ["1"]
}

After this object is build, the id for the look up is taken and checked if the object contains the property. 构建此对象后,将获取查找的ID,并检查该对象是否包含该属性。 While all peopertys are arrays, it is possible to iterate over go() and get all id for collecting. 虽然所有peopertys都是数组,但可以遍历go()并获取所有id以进行收集。 If there is another child, the recursive iteration is going on. 如果有另一个子节点,则递归迭代正在进行。

 var data = [{ "_id": "1", "parentId": "thisPostId", "topLevelId": "1", "text": "<p>comment</p>", }, { "_id": "2", "parentId": "1", "topLevelId": "1", "text": "<p>reply to comment</p>", }, { "_id": "3", "parentId": "2", "topLevelId": "1", "text": "<p>reply to reply to comment</p>", }, { "_id": "4", "parentId": "3", "topLevelId": "1", "text": "<p>reply to reply to reply to comment</p>", }]; function getConnected(s) { function go(a) { r.push(a); o[a] && o[a].forEach(go); } var o = data.reduce(function (r, a) { r[a.parentId] = r[a.parentId] || []; r[a.parentId].push(a._id); return r; }, {}), r = [s]; o[s] && o[s].forEach(go); return r; } for (var i = 1; i <= 4; i++) { document.write('"' + i + '": ' + JSON.stringify(getConnected(i.toString())) + '<br>'); } 

In the OP's comments, you said you're using meteorjs and you seem to want to cascade delete a document. 在OP的评论中,你说你正在使用meteorjs而你似乎想要级联删除文档。 Meteorjs hooks allow this easily: Meteorjs钩子可以轻松实现:

var idToRemove;
Coll.remove({ _id: idToRemove }, callback);

// what to do after removing a Coll document
Coll.after.remove(function (userId, doc) {
    Coll.remove({ parentId: doc._id });
});

You need to install the collection-hooks package first. 您需要先安装collection-hooks包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM