Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Categorize array of objects into a new array

I have an array and I need to map this array into an array of its children.

var data = [{
    name: 'Cars',
    content: 'BMW',
    value: 2000
  },
  {
    name: 'Cars',
    content: 'Fiat',
    value: 542
  },
  {
    name: 'Cars',
    content: 'Mercedes',
    value: 745
  },
  {
    name: 'Cars',
    content: 'Toyota',
    value: 965
  },
  {
    name: 'Cars',
    content: 'Honda',
    value: 754
  }, {
    name: 'Cars',
    content: 'VW',
    value: 123
  },
  {
    name: 'Cars',
    content: 'Ford',
    value: 200
  },
  {
    name: 'Fruits',
    content: 'Apple',
    value: 500
  }, {
    name: 'Fruits',
    content: 'Orange',
    value: 769
  }, {
    name: 'Fruits',
    content: 'Banana',
    value: 120
  }, {
    name: 'Fruits',
    content: 'Strawberry',
    value: 48
  }, {
    name: 'Fruits',
    content: 'Mango',
    value: 653
  },
  {
    name: 'Colors',
    content: 'Red',
    value: 965
  }, {
    name: 'Colors',
    content: 'Black',
    value: 931
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 423
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 964
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 436
  }
]

The end result what I want must be like this:

[
  {
    name: "Children Array",
    children: [
      {
        name: "Cars",
        children: [
          {
            name: "BMW",
            value: 2000
          }, 
          {
            name: "Fiat",
            value: 542
          }, 
          {
          ...
          }
        ]
      },
      {
        name: "Fruits",
        children: [
          {
            name: 'Apple',
            value: 500
          }, 
          {
            name: 'Orange',
            value: 769
          }, 
          {
            ...
          }
        ]
      }, 
      {
        name: "Colors",
        children: [
          {
            name: 'Red',
            value: 965
          }, 
          {
            ...
          }
        ]
      }
    ]
  }
]

This is what I did.

var data = [{
    name: 'Cars',
    content: 'BMW',
    value: 2000
  },
  {
    name: 'Cars',
    content: 'Fiat',
    value: 542
  },
  {
    name: 'Cars',
    content: 'Mercedes',
    value: 745
  },
  {
    name: 'Cars',
    content: 'Toyota',
    value: 965
  },
  {
    name: 'Cars',
    content: 'Honda',
    value: 754
  }, {
    name: 'Cars',
    content: 'VW',
    value: 123
  },
  {
    name: 'Cars',
    content: 'Ford',
    value: 200
  },
  {
    name: 'Fruits',
    content: 'Apple',
    value: 500
  }, {
    name: 'Fruits',
    content: 'Orange',
    value: 769
  }, {
    name: 'Fruits',
    content: 'Banana',
    value: 120
  }, {
    name: 'Fruits',
    content: 'Strawberry',
    value: 48
  }, {
    name: 'Fruits',
    content: 'Mango',
    value: 653
  },
  {
    name: 'Colors',
    content: 'Red',
    value: 965
  }, {
    name: 'Colors',
    content: 'Black',
    value: 931
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 423
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 964
  }, {
    name: 'Colors',
    content: 'BMW',
    value: 436
  }
]

const layer1 = _.uniqWith(_.map(data, (item) => {
  return item.name
}), _.isEqual)

const newArray = [{
  name: 'Children Array',
  children: _.map(layer1, (item) => {
    return {
      name: item,
      children: _.map(data, (item) => {
        return {

        }
      })
    }
  })
}]

console.log(newArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

I do not know how to proceed with the second children layer.

Please advice.

like image 592
a2441918 Avatar asked Jan 28 '23 06:01

a2441918


2 Answers

You could group the data and give the result the final layout.

var data = [{ name: 'Cars', content: 'BMW', value: 2000 }, { name: 'Cars', content: 'Fiat', value: 542 }, { name: 'Cars', content: 'Mercedes', value: 745 }, { name: 'Cars', content: 'Toyota', value: 965 }, { name: 'Cars', content: 'Honda', value: 754 }, { name: 'Cars', content: 'VW', value: 123 }, { name: 'Cars', content: 'Ford', value: 200 }, { name: 'Fruits', content: 'Apple', value: 500 }, { name: 'Fruits', content: 'Orange', value: 769 }, { name: 'Fruits', content: 'Banana', value: 120 }, { name: 'Fruits', content: 'Strawberry', value: 48 }, { name: 'Fruits', content: 'Mango', value: 653 }, { name: 'Colors', content: 'Red', value: 965 }, { name: 'Colors', content: 'Black', value: 931 }, { name: 'Colors', content: 'BMW', value: 423 }, { name: 'Colors', content: 'BMW', value: 964 }, { name: 'Colors', content: 'BMW', value: 436 }],
    result = _(data)
        .groupBy('name')
        .map((group, name) => 
            ({ name, children: _.map(group, ({ content: name, value }) => ({ name, value })) }))
        .value(),
    final = [{ name: "Children Array", children: result }];

console.log(final);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
like image 168
Nina Scholz Avatar answered Jan 31 '23 02:01

Nina Scholz


You can also do that with ES6 only via Object.entries & reduce:

var data = [{ name: 'Cars', content: 'BMW', value: 2000 }, { name: 'Cars', content: 'Fiat', value: 542 }, { name: 'Cars', content: 'Mercedes', value: 745 }, { name: 'Cars', content: 'Toyota', value: 965 }, { name: 'Cars', content: 'Honda', value: 754 }, { name: 'Cars', content: 'VW', value: 123 }, { name: 'Cars', content: 'Ford', value: 200 }, { name: 'Fruits', content: 'Apple', value: 500 }, { name: 'Fruits', content: 'Orange', value: 769 }, { name: 'Fruits', content: 'Banana', value: 120 }, { name: 'Fruits', content: 'Strawberry', value: 48 }, { name: 'Fruits', content: 'Mango', value: 653 }, { name: 'Colors', content: 'Red', value: 965 }, { name: 'Colors', content: 'Black', value: 931 }, { name: 'Colors', content: 'BMW', value: 423 }, { name: 'Colors', content: 'BMW', value: 964 }, { name: 'Colors', content: 'BMW', value: 436 }]

const groupData = (d) => {
  let g = Object.entries(d.reduce((r,c)=>(r[c.name]=[...r[c.name]||[], c],r),{}))
  return g.reduce((r,c) => (r.children.push(
     {name: c[0], children: c[1]}), r),{name: "Children Array", children:[]})}

console.log(groupData(data))

The idea is via the first grouping to get an object with the name groups and after that you simply get the entries on that object and reduce on them to get the final result.

Also you start the main reduce with your predefined object etc.

like image 32
Akrion Avatar answered Jan 31 '23 04:01

Akrion