Reputation: 69
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?
Upvotes: 5
Views: 9215
Reputation: 357
@TheChetan's answer is far from ideal IMO it does not work well when the order of the elements in the initial array is not a happy order (unless it's a desired behavior but I doubt it).
Find below my proposal of solving it:
export const groupArrayByElementKey = (arr = [], key) => {
if (!arr.some(el => key in el)) {
return arr;
}
return arr.reduce((acc, curr) => {
const existingGroupIndex = acc.findIndex(el => el[0][key] === curr[key]);
if (!acc[existingGroupIndex]) {
return acc.concat([[curr]]);
} else {
acc[existingGroupIndex].push(curr);
}
return acc;
}, []);
};
Upvotes: 0
Reputation: 911
I would argue, that it's not question, just asking for code writing... Nonetheless
Array.prototype.group_by_sequenced = function (field_name){
var result = new Array();
var j=0;
for (var i=0;i<this.length;i++){
var tmp = this[i];
if (i==0) {
result[j]= new Array();
} else if (this[i-1][field_name]!=this[i][field_name]) {
j++;
result[j] = new Array();
}
result[j].push(tmp);
}
return result;
}
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" }];
var res = flightPlanCoordinates.group_by_sequenced('status');
console.log(res);
Upvotes: 0
Reputation: 4616
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"))
Upvotes: 1
Reputation: 11011
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));
Upvotes: 1
Reputation: 386868
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>');
Upvotes: 5