2017-06-23 3 views
5

Ich arbeite an einem Problem, wo ich ein Array von Objekten von einem Formular in ein anderes gruppieren muss.Javascript Objekt Reorganisation mit Leistung

Ein Beispiel ist besser als 1000 Worte:

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 
    }, 
]; 

Und das neue Objekt sollte wie folgt aussehen:

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" } 
     ] 
    } 
    ] 
}; 

Ich einzigartige Häuser jeweils mit all ihren Zimmern und auch hinzufügen finden müssen Preis vom ursprünglichen Objekt im Zimmer.

Ich frage mich, welcher wäre der beste Weg, dies zu tun, da ich eine riesige Menge an Elementen haben werde?

Ich habe einige Ideen mit mehreren Schleifen, aber mir scheint es ein bisschen zu komplex meine Lösung.

Update: meine Frage ist nicht das gleiche wie der eine Kandidat für die Duplizierung, weil ich nicht lodash verwende, und mein Objekt muss ein wenig refaktoriert werden, nicht nur neu gruppiert.

Mögliche Lösung (inspiriert von @ Gael Antwort)

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

Es sieht aus wie Sie nur eine Schleife benötigen würde. Du könntest jedes Element durchgehen und es zu einem neuen Array hinzufügen, das basierend auf dem Haus gruppiert wird, dann Räume und dann ID. – victor

+2

Sie sollten diese Ideen und was Sie bisher geschrieben haben, um das Problem zu lösen. – chazsolo

+1

Mögliches Duplikat von [Gruppierung von Objekten nach Schlüssel] (https: // stackoverflow.com/questions/40774697/how-to-group-array-of-objects-by-key) –

Antwort

4

Verwenden Array#reduce mit einem Helferobjekt:

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

Sie können auch erreichen, ist es ES6 Karte verwenden und verbreiten 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);

2

Sie eine Karte verwenden soll:

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 

Oder:

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

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

das ist nur eine andere Datenstruktur, aber was ist die Strategie zu gruppieren, in der Art, die ich brauche? –

+1

@V.Sambor machen Objekte eines Hauses Klassenschlüssel und Räume Array mit Raumobjekten seinen Wert. –

+1

Vielen Dank für Ihre Hilfe, ich werde versuchen, gleich wieder da zu sein! :) –

1

Je nachdem, ob Sie die ursprünglichen Daten erhalten wollen oder nicht beeinflussen die Lösung. Ich habe angenommen, dass Sie das ursprüngliche Objekt beibehalten und ein neues Objekt erstellen möchten.

Sie können dies in einer einzelnen Schleife tun, wenn Sie ein Map Objekt verwenden, um sich daran zu erinnern, wo vorhandene Häuser von dort id Eigentum sind. Wenn das Haus bereits in das Ergebnis eingefügt wurde, müssen Sie nur den neuen Raum hinzufügen. Andernfalls müssen Sie ein neues Hausobjekt erstellen und dessen Index in der Karte speichern.

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