Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

split array of objects in javascript into separate arrays based on a property

I have an array like this:

var flightPlanCoordinates = [
  { lat: 37.772, lng: -122.214, status: "walking" },
  { lat: 36.772, lng: -123.214, status: "walking" },
  { lat: 21.291, lng: -157.821, status: "automotive" },
  { lat: -18.142, lng: 178.431, status: "automotive" },
  { lat: -27.467, lng: 153.027, status: "walking" },
  { lat: -26.467, lng: 151.027, status: "walking" },
];

and I want this to be split up into three arrays that have objects that have the same type like this following format:

[{lat: 37.772, lng: -122.214, status: 'walking'},
{lat: 36.772, lng: -123.214, status: 'walking'}]

[{lat: 21.291, lng: -157.821, status: 'automotive'},
{lat: -18.142, lng: 178.431, status: 'automotive'}]

[{lat: -27.467, lng: 153.027, status: 'walking'}
{lat: -26.467, lng: 151.027, status: 'walking'}]

I cannot just use groupBy to handle this, any ideas?

like image 232
Wenhan Hou Avatar asked Apr 13 '16 04:04

Wenhan Hou


3 Answers

You could use Array#reduce() with a group change if status is changing.

var flightPlanCoordinates = [{ lat: 37.772, lng: -122.214, status: 'walking' }, { lat: 36.772, lng: -123.214, status: 'walking' }, { lat: 21.291, lng: -157.821, status: 'automotive' }, { lat: -18.142, lng: 178.431, status: 'automotive' }, { lat: -27.467, lng: 153.027, status: 'walking' }, { lat: -26.467, lng: 151.027, status: 'walking' }],
    grouped = flightPlanCoordinates.reduce(function (r, a, i) {
        if (!i || r[r.length - 1][0].status !== a.status) {
            return r.concat([[a]]);
        }
        r[r.length - 1].push(a);
        return r;
    }, []);

document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
like image 131
Nina Scholz Avatar answered Nov 17 '22 12:11

Nina Scholz


Use for-loop, When the current element status is different from previous elements status, Then push the slice of array to output array.

const split = (arr) => {
  const output = [];
  let last = 0;
  for (let i = 1; i <= arr.length; i++) {
    if (arr[i]?.status !== arr[i - 1]?.status) {
      output.push(arr.slice(last, i));
      last = i;
    }
  }
  return output;
};

var flightPlanCoordinates = [
  { lat: 37.772, lng: -122.214, status: "walking" },
  { lat: 36.772, lng: -123.214, status: "walking" },
  { lat: 21.291, lng: -157.821, status: "automotive" },
  { lat: -18.142, lng: 178.431, status: "automotive" },
  { lat: -27.467, lng: 153.027, status: "walking" },
  { lat: -26.467, lng: 151.027, status: "walking" },
];

console.log(split(flightPlanCoordinates));
like image 21
Siva K V Avatar answered Nov 17 '22 14:11

Siva K V


First we need to create a groupBy function as described in Nina's Answer. Then attach this function to the prototype of the array object so it becomes available globally like map and reduce. It can then be accessed using array.groupBy(key). The newly defined groupBy function will be available for all other arrays as well.

var flightPlanCoordinates = [
  { lat: 37.772, lng: -122.214, status: "walking" },
  { lat: 36.772, lng: -123.214, status: "walking" },
  { lat: 21.291, lng: -157.821, status: "automotive" },
  { lat: -18.142, lng: 178.431, status: "automotive" },
  { lat: -27.467, lng: 153.027, status: "walking" },
  { lat: -26.467, lng: 151.027, status: "walking" },
];


Array.prototype.groupBy = function(key) {
    return this.reduce(function (r, a, i) {
        if (!i || r[r.length - 1][0][key] !== a[key]) {
            return r.concat([[a]]);
        }
        r[r.length - 1].push(a);
        return r;
    }, []);
};

console.log(flightPlanCoordinates.groupBy("status"))
like image 1
TheChetan Avatar answered Nov 17 '22 12:11

TheChetan