Home > front end >  Grouping elements of array on the basis of property
Grouping elements of array on the basis of property

Time:02-18

I have a array as follows:

data = [
{
  "id":1
  "name":"london"
},
{
  "id":2
  "name":"paris"
},
{
  "id":3
  "name":"london"
},
{
  "id":4
  "name":"paris"
},
{
  "id":5
  "name":"australia"
},
{
  "id":6
  "name":"newzearland"
}
]

At runtime this array can have n number of elements. I want to group this array with respect to name attribute. All the elements with same name should be moved to a separate array. I don't know the what value can name have in advance. This is coming at runtime. For example, from above array I want final output as follows:

output:

newArray1 = [
 {
  "id":1
  "name":"london"
},
{
  "id":3
  "name":"london"
}
]

newArray2 = [
{
  "id":2
  "name":"paris"
},
{
  "id":4
  "name":"paris"
}
]

newArray3 = [
{
  "id":5
  "name":"australia"
}
]

newArray4 = [
{
  "id":6
  "name":"newzearland"
}
]

How can I do that?

CodePudding user response:

here's a working groupBy function =>

function groupBy(arrayObjects, key) {
    return arrayObjects.reduce(function(result, currentObject) {
        const val = currentObject[key]
        result[val] = result[val] || []
        result[val].push(currentObject)
        return result
    }, {})
}

you will call it like this =>

const res = groupBy(data,name)

CodePudding user response:

As Teemu has already pointed out in a comment, creating new variables to store the data is not ideal. You would have no way of knowing how many groups you've created and using variables that you can't be sure exist is not the best way to write code. Fortunately, JavaScript has objects, which can store data like this in a much cleaner way. Here's the code I've come up with:

function groupBy(arr, key) {
    let res = {}
    for (let element of arr) {
        if (res.hasOwnProperty(element[key])) {
            res[element[key]].push(element)
        } else {
            res[element[key]] = [element]
        }
    }

    return res
}

This code is not the best, most efficient code ever, but it is written to be easier to understand for someone still learning. This code loops over every element in your data and checks whether our result already contains an array for elements with that name. If there's already an array for elements with that name, the current element is added to it. If there isn't one, a new one is created with the current element inside it. To do exactly what you want, you'd call this function with groupBy(data, "name") and assign it to a new variable like groupedData (THIS DOES NOT MODIFY THE DATA, IT RETURNS A NEW OBJECT OF GROUPED DATA) .

CodePudding user response:

Нou can get the expected result by using grouping by key approach.

const data = [{"id":1,"name":"london"},{"id":2,"name":"paris"},{"id":3,"name":"london"},{"id":4,"name":"paris"},{"id":5,"name":"australia"},{"id":6,"name":"newzearland"}];

const result = Object.values(data.reduce((acc, obj) => 
  ({ ...acc, [obj.name]: acc[obj.name] ? [...acc[obj.name], obj] : [obj] }), {}));

console.log(result);

const [newArray1, newArray2, newArray3, newArray4,  ...rest] = result;
console.log('newArray1:', newArray1);
console.log('newArray2:', newArray2);
console.log('newArray3:', newArray3);
console.log('newArray4:', newArray4);
.as-console-wrapper{min-height: 100%!important; top: 0}

CodePudding user response:

Start by getting all the unique .names, then map them to the original array filtered by each .name:

const data = [{
        "id": 1, "name": "london"
    },
    {
        "id": 2, "name": "paris"
    },
    {
        "id": 3, "name": "london"
    },
    {
        "id": 4, "name": "paris"
    },
    {
        "id": 5, "name": "australia"
    },
    {
        "id": 6, "name": "newzearland"
    }
];

const newData = [...new Set(data
//Get all names in an array
.map(({name}) => name))]
//For each name filter original array by name
.map(n => data.filter(({name}) => n === name));

console.log( newData );
//OUTPUT: [newArray1, newArray2, .....]

  • Related