我正在研究一个问题,我必须将一个对象数组从一个表单分组到另一个表单。
一个例子优于1000字:
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 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" }
]
}
]
};
我必须找到所有房间的独特房屋,并从房间内的初始物品中添加每个价格。
我想知道哪个是最好的方法,因为我会有大量的元素?
我有一些关于多个循环的想法,但对我而言,我的解决方案似乎有点过于复杂。
更新:我的问题与复制的候选人不一样,因为我不使用lodash,我的对象必须稍微重构,而不仅仅是重新组合。
可能的解决方案(灵感来自@ Gael的回答)
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);
答案 0 :(得分:4)
将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);
与辅助对象一起使用:
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);
您也可以使用ES6 Map和spread语法实现它:
import re
s = """`Hel"lo` 2* "Hel`lo\""""
print([x.group(2) for x in re.finditer(r"([\"'`])(.*?)\1", s)])
答案 1 :(得分:2)
你应该使用地图:
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
或者:
myMap.set(keyObj, 'value associated with keyObj'); // should be rooms
myMap.size; // the number of items you added
答案 2 :(得分:1)
取决于您是否要保留初始数据会影响解决方案。我以为你想保留原始对象并生成一个新对象。
如果使用Map
对象来记住现有房屋所在的id
属性,则可以在单个循环中执行此操作。如果房子已经插入到结果中,您只需要添加新房间。否则,您需要创建一个新的house对象并将其存储在地图中。
function transformHouses(houses) {
const houseMap = new Map();
const result = {houses: []};
for(const house of houses) {
if(houseMap.has(house.id)) {
const index = houseMap.get(house.id);
const room = Object.assign({price: house.price}, house.room);
result.houses[index].rooms.push(room);
} else {
const room = Object.assign({price: house.price}, house.room);
const entry = Object.assign({rooms: [room]}, house.house)
housesMap.set(house.id, result.houses.length);
result.houses.push(entry);
}
}
return result;
}
答案 3 :(得分:1)
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;
});
&#13;