9

Using lodash, how could I group the names of people that have the same birthdates as seen below?

I wrote this out using nested for loops but was thinking there would be a more elegant way of doing this in lodash. I haven't used it much and trying to figure out which function to use.

[
    { "birthdate": "1993", "name": "Ben" },
    { "birthdate": "1994", "name": "John" },
    { "birthdate": "1995", "name": "Larry" },
    { "birthdate": "1995", "name": "Nicole" },
    { "birthdate": "1996", "name": "Jane" },
    { "birthdate": "1996", "name": "Janet" },
    { "birthdate": "1996", "name": "Dora" },
]

to

[
    { "birthdate": "1993", "names": [ "Ben" ] }, 
    { "birthdate": "1994", "names": [ "John"] },
    { "birthdate": "1995", "names": [ "Larry", "Nicole" ] }, 
    { "birthdate": "1996", "names": [ "Jane", "Janet", "Dora" ] }        
]
Thibs
  • 8,058
  • 13
  • 54
  • 85

5 Answers5

20

You can use groupBy() to group each item in the collection by birthdate. After grouping the items, you can use map() to iterate each groups and form them into a new format that includes a birthdate and names. To acquire an array of names from the grouped items, you can use the map() function again to return all the name values.

var result = _(source)
    .groupBy('birthdate')
    .map(function(items, bdate) {
      return {
        birthdate: bdate,
        names: _.map(items, 'name')
      };
    }).value();

var source = [
    { "birthdate": "1993", "name": "Ben" },
    { "birthdate": "1994", "name": "John" },
    { "birthdate": "1995", "name": "Larry" },
    { "birthdate": "1995", "name": "Nicole" },
    { "birthdate": "1996", "name": "Jane" },
    { "birthdate": "1996", "name": "Janet" },
    { "birthdate": "1996", "name": "Dora" },
];
  
var result = _(source)
    .groupBy('birthdate')
    .map(function(items, bdate) {
      return {
        birthdate: bdate,
        names: _.map(items, 'name')
      };
    }).value();

document.body.innerHTML = '<pre>' + JSON.stringify(result, 0, 4) + '</pre>';
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
ryeballar
  • 29,658
  • 10
  • 65
  • 74
  • @ballar Thanks It worked for me but Is there any way to group elements by date only where in the array of objects we have a dateTime property... refer : (https://stackoverflow.com/questions/48562519/how-to-group-elements-using-lodash-group-by-angular-2-4) – Aakriti.G Feb 02 '18 at 06:35
3

You can chain groupBy and map to achieve this.

_.chain(yourArray)
.groupBy('birthdate')
.toPairs()
.map(s=>{
return _.zipObject(['birthdate','names'],s)
})
.map(s=>{
s.names=_.map(s.names,x=>x.name);
return s;
})
.value()
Waqas Noor
  • 911
  • 6
  • 12
3

You can use reduce() and find()

   let arr = [{
 "birthdate": "1993",
 "name": "Ben"
},
{
 "birthdate": "1994",
 "name": "John"
},
{
 "birthdate": "1995",
 "name": "Larry"
},
{
 "birthdate": "1995",
 "name": "Nicole"
},
{
 "birthdate": "1996",
 "name": "Jane"
},
{
 "birthdate": "1996",
 "name": "Janet"
},
{
 "birthdate": "1996",
 "name": "Dora"
},
];

const res = arr.reduce((ac, a) => {
let temp = ac.find(x => x.birthdate === a.birthdate);
if (!temp) ac.push({ ...a,
 name: [a.name]
})
else temp.name.push(a.name)
return ac;
}, [])
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Divyesh Kanzariya
  • 3,629
  • 3
  • 43
  • 44
1

An simple and customizable pure javascript function to return an array of objects grouped by the attribute needed in the object

export const groupArrayBy = (arr, groupBy) => {

    let newArr = []
    arr.map((item) => {
        if(item[groupBy]) {
            let finded = newArr.filter((newItem) => newItem[groupBy] === item[groupBy])
            if(finded.length > 0) {
                finded[0].products.push(item)
            } else {
                newArr.push({category: item[groupBy], products: [item]})
            }
        }
    })

    return newArr
}

Igor Trindade
  • 111
  • 2
  • 5
0

Lodash shortand

var data=[
    { "birthdate": "1993", "name": "Ben" },
    { "birthdate": "1994", "name": "John" },
    { "birthdate": "1995", "name": "Larry" },
    { "birthdate": "1995", "name": "Nicole" },
    { "birthdate": "1996", "name": "Jane" },
    { "birthdate": "1996", "name": "Janet" },
    { "birthdate": "1996", "name": "Dora" },
];


var list= _(data)
    .groupBy('birthdate')
    .map((items, birthdate)=> ({birthdate: birthdate,names: _.map(items, 'name')
      })).value();
      
      console.log(list)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Balaji
  • 9,657
  • 5
  • 47
  • 47