Reputation: 1164
Data is useless unless it is well structured. I want to convert array of objects into a more meaningfully structured object via vanilla JavaScript and by this - to lessen entropy in the world :)
Companies' values form nested named arrays as well as vehicles' values form nested named objects. The hardest task was to set if-statements dynamically. I got stuck in the end of the code, yet, hoping that a JS professional could help me out.
// Source data format
var inputs = [
{"vehicle":"car", "company":"Toyota", "model":"Corolla"},
{"vehicle":"car", "company":"Toyota", "model":"Rav4"},
{"vehicle":"car", "company":"Toyota", "model":"Camry"},
{"vehicle":"car", "company":"Chevrolet", "model":"Malibu"},
{"vehicle":"car", "company":"Chevrolet", "model":"Camaro"},
{"vehicle":"rocket", "company":"Tesla", "model":"SpaceX"}
];
// Target data format
const data = {
car:{
Toyota:[
{"vehicle"="car","company"="Toyota", "model"="Corolla"},
{"vehicle"="car","company"="Toyota", "model"="Rav4"},
{"vehicle"="car","company"="Toyota", "model"="Camry"}
],
Chevrolet:[
{"vehicle"="car","company"="Chevrolet", "model"="Malibu"},
{"vehicle"="car","company"="Chevrolet", "model"="Camaro"}
]
},
rocket:{
Tesla:[
{"vehicle"="rocket","company"="Tesla", "model"="SpaceX"}
]
}
};
// Unfinished solution
// Get all vehicle names.
var vehicles = [];
for (var [key, obj] of inputs.entries()) {
vehicles.push(obj.vehicle);
}
// Single out only unique vehicle names.
var uniqueVehicles = [...new Set(vehicles)];
// Get all company names.
var arr = [];
for (var [key, obj] of inputs.entries()) {
arr.push(obj.company);
}
// Single out only unique company names.
var uniqueCompanies = [...new Set(arr)];
// Group objects into arrays by company names.
var dataProperties = {};
for (var comp of uniqueCompanies) {
dataProperties[comp] = inputs.filter(obj => obj.company === comp);
}
// Group objects into arrays by vehicle names.
var data = {};
for (var vehi of uniqueVehicles) {
data[vehi] = inputs.filter(o => o.vehicle === vehi);
}
// data;
// dataProperties;
Upvotes: 1
Views: 89
Reputation: 386654
You could take a more advanced version with an array of the wanted keys for nesting the wanted properties. This approach is a bit different than the other answer.
The key part is to generate, if necessary and return the last array for pushing an object to the result set,
groups.reduce((p, k, i, { length }) => p[o[k]] = p[o[k]] || (i + 1 === length ? [] : {}), r)
where you have
p
an object as accumulator, starting with the final result object,k
the key for grouping,i
the actual index of the groups array,length
of the groups array for a following check, if the last item is used.Inside of the callback, the value of the wanted property o[k]
is used to access the object p
and if not truthy, like undefined
, then an array of if the last key is taken, then an array is taken.
var array = [{ vehicle: "car", company: "Toyota", model: "Corolla" }, { vehicle: "car", company: "Toyota", model: "Rav4" }, { vehicle: "car", company: "Toyota", model: "Camry" }, { vehicle: "car", company: "Chevrolet", model: "Malibu" }, { vehicle: "car", company: "Chevrolet", model: "Camaro" }, { vehicle: "rocket", company: "Tesla", model: "SpaceX" }],
groups = ["vehicle", "company"],
result = array.reduce((r, o) => {
groups
.reduce((p, k, i, { length }) => p[o[k]] = p[o[k]] || (i + 1 === length ? [] : {}), r)
.push(o);
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 85022
Here's how i would do it:
function transform(data) {
let result = {};
data.forEach(element => {
// Reuse the existing vehicle object, or create an empty one if it doesn't exist
result[element.vehicle] = result[element.vehicle] || {};
// Reuse the existing company array, or create an empty one if it doesn't exist
result[element.vehicle][element.company] = result[element.vehicle][element.company] || [];
result[element.vehicle][element.company].push(element);
})
return result;
}
const inputs = [
{"vehicle":"car", "company":"Toyota", "model":"Corolla"},
{"vehicle":"car", "company":"Toyota", "model":"Rav4"},
{"vehicle":"car", "company":"Toyota", "model":"Camry"},
{"vehicle":"car", "company":"Chevrolet", "model":"Malibu"},
{"vehicle":"car", "company":"Chevrolet", "model":"Camaro"},
{"vehicle":"rocket", "company":"Tesla", "model":"SpaceX"}
];
const output = transform(inputs);
console.log(output);
Upvotes: 2