动态地从对象数组创建嵌套的json

时间:2016-05-10 02:56:14

标签: javascript json mongodb meteor recursion

我有像这样的对象数组

{ title: "A", parent_id: "root",has_children: true}

{ title: "A1", parent_id: "A",has_children: true}

{ title: "A11", parent_id: "A1",has_children: false}
{ title: "A12", parent_id: "A1",has_children: false}
{ title: "A13", parent_id: "A1",has_children: false}

{ title: "B", parent_id: "root",has_children: true}

{ title: "B1", parent_id: "A",has_children: true}

{ title: "B11", parent_id: "B1",has_children: false}
{ title: "B12", parent_id: "B1",has_children: false}
{ title: "B13", parent_id: "B1",has_children: false}

每条记录都有params表示它是否有孩子以及该卡的父母是什么。

记录“root”是顶级卡片。

从上面的数据我想要下面的内容

[
  {
    "title": "A",
    "children": [
      {
        "title": "A1",
        "children": [
          {
            "title": "A11"
          },
          {
            "title": "A12"
          },
          {
            "title": "A13."
          }
        ]
      },
      {
        "title": "A2",
        "children": [
          {
            "title": "A21"
          },
          {
            "title": "A22"
          },
          {
            "title": "A23"
          }
        ]
      }
    ]
  },
  {
    "title": "B",
    "children": [
      {
        "title": "B1",
        "children": [
          {
            "title": "B11"
          },
          {
            "title": "B12"
          },
          {
            "title": "B13."
          }
        ]
      },
      {
        "title": "B2",
        "children": [
          {
            "title": "B21"
          },
          {
            "title": "B22"
          },
          {
            "title": "B23"
          }
        ]
      }
    ]
  }
]

我想尝试一段时间但是做不到,这就是我试过的

我正在使用mongodb

在流星中这样做
getUserJSON  = function(userId){
  var userJSON = [];
  getJSONCards(userId,'root', userJSON)

}

getJSONCards = function(userId, parent_id, userData){
  var allCards = userCards.find({ $and: [ { user_id: userId }, { parent_id: parent_id } ] }).fetch();
  if(allCards.length > 0){
    allCards.forEach(function (cardInfo) {
      var isExist = $.grep(userData, function(e){ return e.content === parent_id; });
      if(isExist){
        //here I don't know how to insert nested cards
      }
    });
  }
}

但我希望简单的js解决方案

2 个答案:

答案 0 :(得分:3)

以下解决方案使用以下方法:

  1. 使用Array.prototype.reduce(),通过title集合中各自的allCards值将每个项目编入对象。
  2. 使用Array.prototype.filter()保留集合中的root项,同时将每个项目作为子项分配给各自的父项(如果它们存在于indexed变量中)。
  3. var allCards = [
      { title: "A", parent_id: "root", has_children: true},
      { title: "A1", parent_id: "A", has_children: true},
      { title: "A11", parent_id: "A1", has_children: false},
      { title: "A12", parent_id: "A1", has_children: false},
      { title: "A13", parent_id: "A1", has_children: false},
      { title: "B", parent_id: "root", has_children: true},
      { title: "B1", parent_id: "A", has_children: true},
      { title: "B11", parent_id: "B1", has_children: false},
      { title: "B12", parent_id: "B1", has_children: false},
      { title: "B13", parent_id: "B1", has_children: false}
    ];
    
    // index each item by title
    var indexed = allCards.reduce(function(result, item) {
      result[item.title] = item;
      return result;
    }, {});
    
    // retain the root items only
    var result = allCards.filter(function(item) {
      
      // get parent
      var parent = indexed[item.parent_id];
      
      // make sure to remove unnecessary keys
      delete item.parent_id;
      delete item.has_children;
      
      // has parent?
      if(parent) {
        // add item as a child
        parent.children = (parent.children || []).concat(item);
      }
      
      // This part determines if the item is a root item or not
      return !parent;
    });
    
    document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

答案 1 :(得分:1)

这是一种做法。迭代对象数组,为每个对象构建一个新对象并将其存储在缓存中,以便在处理子对象时直接修改该对象。父母必须在孩子面前出现才能工作,否则你必须建立多次通行证。

// define data array
var data = [
    { title: "A", parent_id: "root",has_children: true},

    { title: "A1", parent_id: "A",has_children: true},

    { title: "A11", parent_id: "A1",has_children: false},
    { title: "A12", parent_id: "A1",has_children: false},
    { title: "A13", parent_id: "A1",has_children: false},

    { title: "B", parent_id: "root",has_children: true},

    { title: "B1", parent_id: "A",has_children: true},

    { title: "B11", parent_id: "B1",has_children: false},
    { title: "B12", parent_id: "B1",has_children: false},
    { title: "B13", parent_id: "B1",has_children: false}
];

var root = {};
var parentCache = {};
// for each element definition in the data array
for (var i = 0; i < data.length; i++) {
    var element = data[i];
    var title = element.title;
    // XXX - check for duplicate title here.

    // create a new object and initialize
    var newObj = {"title" : title};
    if (element.has_children) {
        newObj["children"] = [];
    }
    // put this object into its parent
    if (element.parent_id === "root") {
        root[title] = newObj;
    } else {
        // XXX - if the parent isn't defined first this will fail
        var parent = parentCache[element.parent_id];
        parent.children.push(newObj);
    }
    // store this object in case it is a parent
    parentCache[title] = newObj;
}

console.log(JSON.stringify(root));