Search code examples
javascriptarraysobjectunderscore.jslodash

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


I have array of objects like this:

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

and I want to move child objects into parent objects, splitted by the parrent object (there is no given key from child object is belonged to which parrent). So it's only separate by the parent object. To be simple I want to change the array into :

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

I have read lodash about chunk but it's no use.


Solution

  • You can use either the native Array.prototype.reduce function or lodash's 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);

    UPDATE: Small changes using newer ES language features

    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);