break array of objects into separate arrays based on a property

61,331

Solution 1

JQuery and Underscore are both options to use.

Underscore's groupBy does exactly what you need.

_.groupBy(arr, "type")

Solution 2

This is an easy job for Array.reduce(...):

function groupBy(arr, property) {
  return arr.reduce(function(memo, x) {
    if (!memo[x[property]]) { memo[x[property]] = []; }
    memo[x[property]].push(x);
    return memo;
  }, {});
}

var o = groupBy(arr, 'type'); // => {orange:[...], banana:[...]}
o.orange; // => [{"type":"orange","title":"First"},{"type":"orange","title":"Second"}]
o.banana; // => [{"type":"banana","title":"Third"},{"type":"banana","title":"Fourth"}]

Of course, if your target browser(s) do not support ECMAScript 262 5th edition then you'll have to implement "reduce" by yourself, or use a polyfill library, or choose another answer.

[Update] Here's a solution that should work with any version of JavaScript:

function groupBy2(xs, prop) {
  var grouped = {};
  for (var i=0; i<xs.length; i++) {
    var p = xs[i][prop];
    if (!grouped[p]) { grouped[p] = []; }
    grouped[p].push(xs[i]);
  }
  return grouped;
}

Solution 3

This assumes an array of objects:

function groupBy(array, property) {
    var hash = {};
    for (var i = 0; i < array.length; i++) {
        if (!hash[array[i][property]]) hash[array[i][property]] = [];
        hash[array[i][property]].push(array[i]);
    }
    return hash;
}

groupBy(arr,'type')  // Object {orange: Array[2], banana: Array[2]}
groupBy(arr,'title') // Object {First: Array[1], Second: Array[1], Third: Array[1], Fourth: Array[1]}

Solution 4

Just build a dictionary which holds the objects based on their title. You could do it like this:

js

var arr = [
{type:"orange", title:"First"},
 {type:"orange", title:"Second"},
 {type:"banana", title:"Third"},
 {type:"banana", title:"Fourth"}
];
var sorted = {};
for( var i = 0, max = arr.length; i < max ; i++ ){
 if( sorted[arr[i].type] == undefined ){
  sorted[arr[i].type] = [];
 }
 sorted[arr[i].type].push(arr[i]);
}
console.log(sorted["orange"]);
console.log(sorted["banana"]);

jsfiddle demo: http://jsfiddle.net/YJnM6/

Solution 5

ES6 solution:

function groupBy(arr, property) {
  return arr.reduce((acc, cur) => {
    acc[cur[property]] = [...acc[cur[property]] || [], cur];
    return acc;
  }, {});
}

or completely ES6fy:

const groupBy = (arr, property) => {
    return arr.reduce((acc, cur) => {
      acc[cur[property]] = [...acc[cur[property]] || [], cur];
      return acc;
    }, {});
}

I hope it helps!

Share:
61,331
Evan
Author by

Evan

I enjoy StackOverflow because it is so helpful to ask others when you need help and it's also fun to help other people solve interesting problems.

Updated on July 05, 2022

Comments

  • Evan
    Evan almost 2 years

    Say I have an array like this:

    var arr = [
        {type:"orange", title:"First"},
        {type:"orange", title:"Second"},
        {type:"banana", title:"Third"},
        {type:"banana", title:"Fourth"}
    ];
    

    and I want this to be split up into arrays that have objects which have same type so:

    [{type:"orange", title:"First"},
    {type:"orange", title:"Second"}]
    
    [{type:"banana", title:"Third"},
    {type:"banana", title:"Fourth"}]
    

    But I want to do this generically so not having an if statement that specifies orange or banana

    // not like this
    for (prop in arr){
        if (arr[prop] === "banana"){
           //add to new array
        }
    }
    

    Thoughts? JQuery and Underscore are both options to use.

  • Travis J
    Travis J over 11 years
    Might want to also include a version which is compliant with more browsers. reduce is not supported by IE8-.
  • maerics
    maerics over 11 years
    @TravisJ: yes, true, if your target browsers don't support EMCAScript 262 5th edition then you'll need to implement your own "reduce" function or choose one of the other answers.
  • Mark Carpenter Jr
    Mark Carpenter Jr over 6 years
    Works great, also Kudos for calling the pattern a Dictionary!
  • Kate Lupachova
    Kate Lupachova over 3 years
    Just for reference: when calling this function, property argument should be a string.