Reputation: 3195
I have an array of Javascript objects like below.
[{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}]
What I ideally want is to group those of the same value (email) into there own sub array of objects i.e if you look at the array above you will see I have 2 entries for the same person Alex McPherson. What I want to do is the below if possible move and combine into a sub array and the same for any other value that exists more than once.
[[{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}],
[{
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}],
[{
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}]]
I can't seem to get my head around resorting the array.
Upvotes: 1
Views: 1185
Reputation: 7887
Hard to be more efficient than something like this:
const groupBy = (data, groupingProp) => {
// Create a dictionnary of groups.
const map = new Map();
data.forEach(entry => {
const groupKey = entry[groupingProp];
const list = map.get(groupKey);
if (list == null) {
map.set(groupKey, [entry]);
} else {
list.push(entry);
}
});
// Transform it back into a list of groups.
return [...map.values()];
}
// The data.
const data = [{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}
];
console.log(groupBy(data, 'email'));
Upvotes: 2
Reputation: 1989
Instead of DIY implementation. You could use ramda groupWith
Simply
R.groupWith((a ,b) => a.email === b.email, emails)
Upvotes: 0
Reputation: 70
let emails = [{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}];
let emails_obj = [];
let output_array = [];
emails.forEach(function(obj) {
if (emails_obj[obj.email] == undefined) {
emails_obj[obj.email] = []
emails_obj[obj.email].push(obj);
} else {
emails_obj[obj.email].push(obj);
}
})
for (var key in emails_obj) {
output_array.push(emails_obj[key]);
}
console.log(output_array);
Upvotes: 0
Reputation: 3596
Here is working example. We use ES6 array .reduce()
function.
var data = [{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
},
{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}]
const grouped = data.reduce((previous, current) => {
if (!previous[current.email]) {
const found = previous.find(element => element.email === current.email);
if (found) {
const index = previous.indexOf(found);
previous.splice(index,1);
// We add always at the top
previous.unshift([found, current]);
} else {
previous.push(current);
}
}
return previous;
}, [])
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 350760
You could use an ES6 map to collect the data per email and then extract the resulting values from that map (assuming data
is input):
Array.from(
data.reduce(
(acc, o) => (acc.get(o.email).push(o), acc),
new Map(data.map( o => [o.email, []] ))
), ([key, value]) => value
)
var data = [{
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "40",
"rate": "20",
"amount": "200",
"vat": "60",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}, {
"email": "[email protected]",
"fn": "Mike",
"sn": "Mann",
"phone": "01233xxxxx",
"hours": "50",
"rate": "70",
"amount": "500",
"vat": "90",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}, {
"email": "[email protected]",
"fn": "Fred",
"sn": "Frogg",
"phone": "01233xxxxx",
"hours": "80",
"rate": "90",
"amount": "800",
"vat": "100",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}, {
"email": "[email protected]",
"fn": "Alex",
"sn": "McPherson",
"phone": "01233xxxxx",
"hours": "90",
"rate": "30",
"amount": "900",
"vat": "120",
"agency": "test",
"start": "08/06/2017",
"end": "10/06/2017"
}];
var result = Array.from(
data.reduce(
(acc, o) => (acc.get(o.email).push(o), acc),
new Map(data.map( o => [o.email, []] ))
), ([key, value]) => value
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 386680
You could use a closure over a hash table for the same email address and their items.
var data = [{ email: "[email protected]", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "40", rate: "20", amount: "200", vat: "60", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Mike", sn: "Mann", phone: "01233xxxxx", hours: "50", rate: "70", amount: "500", vat: "90", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Fred", sn: "Frogg", phone: "01233xxxxx", hours: "80", rate: "90", amount: "800", vat: "100", agency: "test", start: "08/06/2017", end: "10/06/2017" }, { email: "[email protected]", fn: "Alex", sn: "McPherson", phone: "01233xxxxx", hours: "90", rate: "30", amount: "900", vat: "120", agency: "test", start: "08/06/2017", end: "10/06/2017" }],
result = data.reduce(function (hash) {
return function (r, o) {
if (!hash[o.email]) {
hash[o.email] = [];
r.push(hash[o.email]);
}
hash[o.email].push(o)
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 3