如何分割javascript数组的对象与特定条件使用lodash/下划线

How to split javascript array of object with specific condition using lodash/underscorejs

本文关键字:特定条件 lodash 下划线 对象 何分割 分割 数组 javascript      更新时间:2023-09-26

我有一个像这样的数组:

var data = [
 {
    type : "parent",
    name : "A"
 },
 {
    type : "child",
    name : "1"
 },
 {
    type : "child",
    name : "2"
 },
 {
    type : "parent",
    name : "B"
 },
 {
    type : "child",
    name : "3"
 }
]

和我想移动子对象到父对象,由父对象分割(没有给定的键从子对象属于哪个父对象)。它只被父对象分开。简单来说,我想把数组改成:

[
  {
    type : "parent",
    name : "A",
    child: [
        {
            type : "child",
            name : "1"
        },
        {
            type : "child",
            name : "2"
        }
    ]
  },
  {
    type : "parent",
    name : "B",
    child: [
        {
            type : "child",
            name : "3"
        }
      ]
  }
]

我读过lodash关于chunk的文章,但是没有用。

您可以使用本地Array.prototype.reduce函数或lodash的reduce:

var data = [{
    type: "parent",
    name: "A"
  },
  {
    type: "child",
    name: "1"
  },
  {
    type: "child",
    name: "2"
  },
  {
    type: "parent",
    name: "B"
  },
  {
    type: "child",
    name: "3"
  }
];
// If using _.reduce then use:
// var newData = _.reduce(data, function(arr, el) {...}, []);
var newData = data.reduce(function(arr, el) {
  if (el.type === 'parent') {
    // If el is pushed directly it would be a reference
    // from the original data object
    arr.push({
      type: el.type,
      name: el.name,
      child: []
    });
  } else {
    arr[arr.length - 1].child.push({
      type: el.type,
      name: el.name
    });
  }
  return arr;
}, []);
console.log(newData);

更新:使用更新的ES语言特性进行小更改

const data = [{
    type: "parent",
    name: "A"
  },
  {
    type: "child",
    name: "1"
  },
  {
    type: "child",
    name: "2"
  },
  {
    type: "parent",
    name: "B"
  },
  {
    type: "child",
    name: "3"
  }
];
const newData = data.reduce((arr, el) => {
  if (el.type === 'parent') {
    // If el is pushed directly it would be a reference
    // from the original data object
    arr.push({...el, child: []});
  } else {
    arr[arr.length - 1].child.push({...el});
  }
  return arr;
}, []);
console.log(newData);

这里有一个可能更容易理解的lodash解决方案。CodePen

注意事项:

  • 这修改传入的数据对象-如果这是一个问题,我们可以抛出一些_.clone()调用。
  • 这将只工作,如果每个父有26或更少的孩子,因为你选择的name: "ab"模式
var lastParent;
var result = _.chain(data)
  .groupBy(function (item) {
    if (item.type === 'parent') lastParent = item.name
    return lastParent
  })
  .map(function (group) {
    var parent = _.first(group)
    parent.child = _.chain(group)
      .slice(1)
      .map(function (child, index) {
        child.name = parent.name.toLowerCase() + String.fromCharCode(index + 97)
        return child 
      })
      .value()
    return parent
  })
  .value()
console.log(result)

纯javascript版本:

var newArr = [];
var j=0;
var k=0;
for (var i = 0; i <data.length; i++) {
    if(data[i].type == 'parent'){
        newArr[j] = data[i];
        newArr[j].children = [];
        j++;
        k=0;
    } 
    else {
        data[i].name = newArr[j-1].name.toLowerCase() + String.fromCharCode(k + 97)
        newArr[j-1].children[k] =data[i];
        k++;
    }
}
console.log(newArr)

我在这里假设父元素总是放在子元素之前,如示例数据中所提供的。

此外,如果你能阻止26岁以上孩子的父母,那就太好了。这将导致String.fromCharCode(k + 97)打印奇怪的字符。请参见http://www.asciitable.com/

for (ele in data)
{
    if (!data[ele].hasOwnProperty('child') && data[ele].type=='parent')
    {
        data[ele].child = [];
        while(data[parseInt(ele) + 1] && data[parseInt(ele) + 1].type == 'child')
        {
            data[ele].child.push({type: data[parseInt(ele) + 1].type, name:data[parseInt(ele) + 1].name});
            data.splice(parseInt(ele) + 1, 1);
        }
    }
}
console.log(data);

尝试简单循环:

var current, parent, result = [], i = 0;
while(current = data[i++]){
    if(current.type === "parent"){
        current.child = [];
        result.push(current);
        parent = current
    }else{
        current.name = (parent.name + String.fromCharCode(parent.child.length + 97)).toLowerCase();
        parent.child.push(current)
    }
}