2017-06-23 63 views
5

我正在處理一個問題,即必須將對象數組從一個表單組合到另一個表單中。具有性能的Javascript對象重組

一個例子是優於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,因此我的問題與重複的候選人不同,我的對象必須重構一點,而不是重新組合。

可能的解決方案(由@啓發蓋爾的答案)

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

它看起來像你只需要一個循環。你可以通過每個元素並將其添加到一個新的數組,然後根據房屋,房間,然後id進行分組。 – victor

+2

您應該發佈這些想法以及迄今爲止寫的內容來解決問題。 – chazsolo

+1

[如何按鍵組織對象數組](https:// stackoverflow。com/questions/40774697/how-to-group-array-of-objects-by-key) –

回答

4

使用Array#reduce用輔助對象:

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);

您也可以使用ES6地圖實現它,傳播語法:

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);

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 
+0

這只是一個不同的數據結構,但按照我需要的方式進行分組的策略是什麼? –

+1

@ V.Sambor使房間類對象和包含房間對象的房間數組具有價值。 –

+1

謝謝你的幫助,我會試試這個,馬上回來! :) –

1

取決於如果你想保留原始數據或不將影響解。我假設你想保留原始對象併產生一個新對象。

如果您使用Map對象記住現有房屋的位置,則可以在單個循環中執行此操作。id屬性。如果房子已插入結果中,則只需添加新房間。否則,您需要創建一個新的房屋對象並將其索引存儲在地圖中。

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; 
} 
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; 
 
    
 
});

相關問題