2017-06-23 11 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-groups-by-key) –

答えて

4

使用Array#reduce

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 

かを

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

あなたはマップを使用する必要がありますヘルパーオブジェクトと

myMap.set(keyObj, 'value associated with keyObj'); // should be rooms 

myMap.size; // the number of items you added 
+0

これは別のデータ構造ですが、必要な方法でグループ化する戦略は何ですか? –

+1

@ V.Samborはhouseクラスのキーオブジェクトを作成し、roomオブジェクトはroomオブジェクトを含んでいます。 –

+1

あなたの助けていただきありがとうございます、私はこれを試してみよう、戻ってきて! :) –

1

溶液。私は元のオブジェクトを保持し、新しいオブジェクトを生成したいと思っています。

Mapオブジェクトを使用して既存の住宅がどこにあるのかを覚えている場合は、このループを1つのループで行うことができます。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; 
 
    
 
});

関連する問題