Reputation: 1216
I have an array of object which I need to convert to a table (kind of pivoting the data). Saying this I need to get another array of objects with the unique titles which have nested arrays of object with pairs of the values. Could you please take a look into this and help with achiving what I need? Please see the original and the desired array below:
Original Array:
[
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title2", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title3", value1: "value1", value2: "value2"},
{title: "Title2", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title3", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
]
Desired result:
[
{title: "Title1", values: [{value1: "value1"}, {value2: "value2"}]},
{title: "Title2", values: [{value1: "value1"}, {value2: "value2"}]},
{title: "Title3", values: [{value1: "value1"}, {value2: "value2"}]},
]
Thanks if advance for any suggestions.
Upvotes: 2
Views: 8232
Reputation: 386620
You could use a hash table for grouping as thisArg
with Array#forEach
.
var data = [{ title: "Title1", value1: "value1", value2: "value2" }, { title: "Title2", value1: "value1", value2: "value2" }, { title: "Title1", value1: "value1", value2: "value2" }, { title: "Title3", value1: "value1", value2: "value2" }, { title: "Title2", value1: "value1", value2: "value2" }, { title: "Title1", value1: "value1", value2: "value2" }, { title: "Title3", value1: "value1", value2: "value2" }, { title: "Title1", value1: "value1", value2: "value2" }],
grouped = [];
data.forEach(function (a) {
// check if title is not in hash table
if (!this[a.title]) {
// if not, create new object with title and values array
// and assign it with the title as hash to the hash table
this[a.title] = { title: a.title, values: [] };
// add the new object to the result set, too
grouped.push(this[a.title]);
}
// create a new object with the other values and push it
// to the array of the object of the hash table
this[a.title].values.push({ value1: a.value1, value2: a.value2 });
}, Object.create(null)); // Object.create creates an empty object without prototypes
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 4
Reputation: 4766
A simple array reduce may be of help
let data = [{
title: "Title1",
value1: "value1",
value2: "value2"
}, {
title: "Title2",
value1: "value1",
value2: "value2"
}, {
title: "Title1",
value1: "value1",
value2: "value2"
}, {
title: "Title3",
value1: "value1",
value2: "value2"
}, {
title: "Title2",
value1: "value1",
value2: "value2"
}, {
title: "Title1",
value1: "value1",
value2: "value2"
}, {
title: "Title3",
value1: "value1",
value2: "value2"
}, {
title: "Title1",
value1: "value1",
value2: "value2"
}];
let pivoted = data.reduce((prev, cur) => {
let existing = prev.find(x => x.title === cur.title);
if (existing)
existing.values.push(cur)
else
prev.push({
title: cur.title,
values: [cur]
});
return prev;
}, []);
console.log(pivoted);
API's used
This could then be adapted to pivot by any field you desire, it would need error handling adding if that field does not exist however:
let pivotBy = (key, data) => data.reduce((prev, cur) => {
let existing = prev.find(x => x[key] === cur[key]);
if (existing) {
existing.values.push(cur);
} else {
let toInsert = {
values: [cur]
}
toInsert[key] = cur[key];
prev.push(toInsert);
}
return prev;
}, []);
EDIT I misinterpreted your desired output format, however the reduce approach could be modified to fulfill that requirement.
Upvotes: 6
Reputation: 424
var originalArray = [
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title2", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title3", value1: "value1", value2: "value2"},
{title: "Title2", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
{title: "Title3", value1: "value1", value2: "value2"},
{title: "Title1", value1: "value1", value2: "value2"},
];
var newArray = [];
for(var i = 0; i<originalArray.length; i++){
var object = {};
object.title=originalArray[i].title;
var values = [];
values.push({value1: originalArray[i].value1});
values.push({value2: originalArray[i].value2});
object.values= values;
newArray.push(object);
}
This will work, although honestly, I don't know why you have some duplicated tittles. I supossed that it was just an example. If not, the answer is another.
Upvotes: 1