unEven一个数组,就像concatAll函数一样

时间:2015-03-31 10:46:46

标签: javascript arrays lodash

我有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"}
          ]
        }
      ]
    }
  ];

我的目标是有一个函数unEven,它将array1转换为array2,我使用lodash在这里执行此操作我现在在哪里:
unEven array1到array2,在这种情况下跟踪属性' name'包含有关此项目应该推送到新数组中的位置的信息,请检查此js bin,此工作适用于3级嵌套数组,但我的目标是让unEven数组不受嵌套级别的限制,这就是' s我被困的地方。
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 angular ui router {{3}},这将从路由JSON文件生成,因为我在JSON中创建路由文件。

1 个答案:

答案 0 :(得分:2)

这是一个重达lodash的解决方案,我认为可以满足您的需求。如果你不关心改变原始数组,你可以跳过克隆,如果你的父母在原始数组中总是有孩子,你可以跳过排序。

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
}