I am working on a problem where I have to group an array of objects from one form into another.
An example is better than 1000 words:
var initialData = [
{
house: { id: 1, text: "white" },
room: { id: 1, text: "red" },
price: 2.1
},
{
house: { id: 1, text: "white" },
room: { id: 2, text: "blue" },
price: 3.1
},
{
house: { id: 1, text: "white" },
room: { id: 3, text: "red" },
price: 5.8
},
{
house: { id: 2, text: "black" },
room: { id: 1, text: "yellow" },
price: 9.1
},
{
house: { id: 2, text: "black" },
room: { id: 2, text: "green" },
price: 7.7
},
];
And the new object should look like this:
var finalObject = {
houses: [
{
id: 1, text: "white",
rooms: [
{ id: 1, text: "red", price: "2.1" },
{ id: 2, text: "blue", price: "3.1" },
{ id: 3, text: "red", price: "5.8" }
]
},
{
id: 2, text: "black",
rooms: [
{ id: 1, text: "yellow", price: "9.1" },
{ id: 2, text: "green", price: "7.7" }
]
}
]
};
I have to find unique houses with all their rooms and also to add each price from initial object inside room.
I'm wondering which would be the best way to do this since I will have a huge amount of elements?
I have some ideas with multiple loops, but to me it seems a bit too complex my solution.
Update: my question is not the same as the one candidate for duplication because I don't use lodash, and my object has to be refactored a bit, not just regrouped.
Possible solution (inspired by @Gael's answer)
finalObject = {}
for (var i = 0; i < initialData.length; ++i) {
var item = initialData[i];
var id = item.house.id;
if(!finalObject[id]) {
finalObject[id] = item.house;
finalObject[id].rooms = [];
}
var room = item.room;
room.price = item.price;
finalObject[id].rooms.push(room);
}
console.log(finalObject);
Use Array#reduce
with a helper object:
var initialData = [{"house":{"id":1,"text":"white"},"room":{"id":1,"text":"red"},"price":2.1},{"house":{"id":1,"text":"white"},"room":{"id":2,"text":"blue"},"price":3.1},{"house":{"id":1,"text":"white"},"room":{"id":3,"text":"red"},"price":5.8},{"house":{"id":2,"text":"black"},"room":{"id":1,"text":"yellow"},"price":9.1},{"house":{"id":2,"text":"black"},"room":{"id":2,"text":"green"},"price":7.7}];
var dict = {}; // helper object
var result = initialData.reduce(function(houses, obj) { // reduce the data
var house = dict[obj.house.id]; // get the house from the dict by id
if(!house) { // if house wasn't found
house = Object.assign({}, obj.house, { rooms: [] }); // create a new house object
houses.push(house); // push it into the array of houses
dict[house.id] = house; // add it to the dict by id
}
house.rooms.push(obj.room); // push the room to the current house
return houses;
}, []);
console.log(result);
You can also achieve it using ES6 Map and spread syntax:
const initialData = [{"house":{"id":1,"text":"white"},"room":{"id":1,"text":"red"},"price":2.1},{"house":{"id":1,"text":"white"},"room":{"id":2,"text":"blue"},"price":3.1},{"house":{"id":1,"text":"white"},"room":{"id":3,"text":"red"},"price":5.8},{"house":{"id":2,"text":"black"},"room":{"id":1,"text":"yellow"},"price":9.1},{"house":{"id":2,"text":"black"},"room":{"id":2,"text":"green"},"price":7.7}];
const result = [...initialData.reduce((houses, { house, room }) => { // reduce the data to a Map
const currentHouse = houses.get(house.id) || Object.assign({}, house, { rooms: [] }); // get the current house from the map by id, or create a new one
currentHouse.rooms.push(room); // push the room to the current house
return houses.set(currentHouse.id, currentHouse); // set the house to the map, and return it
}, new Map()).values()]; // get the values of the map and spread to an array
console.log(result);
You should use a map:
var myMap = new Map();
var keyObj = {}, // ideally your room object with id
// setting the values
myMap.set(keyString, "value associated with 'a string'"); // not recommended for your case
Or:
myMap.set(keyObj, 'value associated with keyObj'); // should be rooms
myMap.size; // the number of items you added
var houses= {};
initialData.forEach(function(item){
if( !houses[ item.house ] ){
houses[ item.house ]= item.house;
houses[ item.house ].rooms= {};
}
houses[ item.house ].rooms[ item.room.id ]= item.room;
houses[ item.house ].rooms[ item.room.id ].price= item.price;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With