unEven 数组,如 concatAll 函数

unEven an array, like the concatAll function

我有这 2 个数组代表相同的数据:

array1 = [
  {name: "max", age: 30},
  {name: "paul"},
  {name: "paul.Jack", age: 25},
  {name: "max.David"},
  {name: "max.Sylvia", age: 27},
  {name: "paul.Jack.Ned"},
  {name: "paul.Jack.Mike"},
  {name: "max.David.Jeff"},
  {name: "max.Sylvia.Anna", age: 5},
  {name: "max.David.Buffy"},
  {name: "max.Sylvia.Craig"},
  {name: "max.Sylvia.Robin"}
];
array2 = [
    {
      name: "max",
      age: 30,
      children: [
        {
          name: "Sylvia",
          age: 27,
          children: [
            {name: "Anna", age: 5},
            {name: "Craig"},
            {name: "Robin"}
          ]
        },
        {
          name: "David",
          children: [
            {name: "Jeff"},
            {name: "Buffy"}
          ]
        }
      ]
    },
    {
      name: "paul",
      children: [
        {
          name: "Jack",
          age: 25,
          children: [
            {name: "Ned"},
            {name: "Mike"}
          ]
        }
      ]
    }
  ];

我的 objective 是有一个函数 unEven 将 array1 转换为 array2,我正在使用 lodash 来做这就是我现在的位置:
unEven array1 到 array2 跟踪 属性 在这种情况下 'name' 包含有关应将此项目推送到新数组中的位置的信息检查此js bin,这适用于 3 级嵌套数组,但我的目标是让它成为不均匀的数组而没有嵌套级别的限制,这就是我遇到的问题。
unEven 函数类似于 video.
中介绍的 concatAll 函数 这是 unEven 函数:

Array.prototype.unEven = function (trackingProperty, children, resultArray) {
  var newItem, prop, index, parent, subParent, subParentIndex;
  resultArray = resultArray || [];
  this.forEach(function (item) {
    newItem = lodash.omit(item, trackingProperty);
    prop    = lodash.pick(item, trackingProperty);
    if (prop[trackingProperty].indexOf('.') === -1) {
      resultArray.push(item);
    } else {
      newItem[trackingProperty] = prop[trackingProperty].split(".");
      parent = {};
      parent[trackingProperty] = newItem[trackingProperty][0];
      index = lodash.indexOf(resultArray, lodash.find(resultArray, parent));
      if (newItem[trackingProperty].length === 2) {
        newItem[trackingProperty] = newItem[trackingProperty][1];
        if (!Array.isArray(resultArray[index][children])) {
          resultArray[index][children] = [];
        }
        resultArray[index][children].push(newItem);
      } else if (newItem[trackingProperty].length === 3) {
        subParent = {};
        subParent[trackingProperty] = newItem[trackingProperty][1];
        subParentIndex = lodash.indexOf(resultArray[index][children], lodash.find(resultArray[index][children], subParent));
        newItem[trackingProperty]   = newItem[trackingProperty][2];
        if (!Array.isArray(resultArray[index][children][subParentIndex][children])) {
          resultArray[index][children][subParentIndex][children] = [];
        }
        resultArray[index][children][subParentIndex][children].push(newItem);
      }
    }
  });
  return resultArray;
};

为了给出我的用例,我试图在我的应用程序中创建一个 d3js tree layout of angular ui router,它将从路由 JSON 文件中生成,因为我在 [=29] 中创建了路由=] 文件.

这是一个 lodash-heavy 解决方案,我认为它可以满足您的需求。如果你不关心改变原始数组,你可以跳过克隆,如果你在原始数组中的 parents 之后总是有 children,则可以跳过排序。

function unEven(array1) {
     _(_.clone(array1, true)) //begin chaining syntax, with cloned array
    .each(function(person) {
        person.name = person.name.split(".") //replace name with array of names
    })
    .sortBy(function(person) {return person.name.length}) //sort so that we handle children after parents
    .reduce(function(result, person) {
        var parentArray = result;
        var name = person.name.pop() //their actual name is the last one in the list
        _.each(person.name, function(parentName) { //loop through parent names to find the proper array to add to
            var parent = _.find(parentArray, {name: parentName});
            if(!parent) throw new Error(name + " has non-existent parent "+parentName);
            parentArray = parent.children = parent.children || []
        })
        person.name = name; //return name back to just being their name
        parentArray.push(person);
        return result;
    }, []) //reduce ends chaining syntax; so no need for .value
}