2017-06-23 17 views
5

Tôi đang khắc phục sự cố trong đó tôi phải nhóm một mảng các đối tượng từ một biểu mẫu này sang dạng khác.Sắp xếp lại đối tượng Javascript với hiệu suất

Một ví dụ là tốt hơn so với 1000 từ:

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

Và đối tượng mới sẽ trông như thế này:

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

tôi phải tìm nhà độc đáo với tất cả các phòng của họ và cũng để thêm mỗi giá từ vật thể ban đầu trong phòng.

Tôi tự hỏi đó sẽ là cách tốt nhất để làm điều này vì tôi sẽ có một số lượng lớn các yếu tố?

Tôi có một số ý tưởng với nhiều vòng lặp, nhưng đối với tôi, có vẻ như một giải pháp quá phức tạp của tôi.

Cập nhật: câu hỏi của tôi không giống như một ứng cử viên cho sao chép vì tôi không sử dụng lodash, và đối tượng của tôi phải được tái cấu trúc một chút, không chỉ tập hợp lại.

giải pháp có thể xảy ra (lấy cảm hứng từ @ câu trả lời Gael của)

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

Dường như bạn sẽ chỉ cần một vòng lặp. Bạn có thể đi qua từng phần tử và thêm nó vào một mảng mới, nhóm nó dựa trên ngôi nhà, sau đó là các phòng, sau đó là id. – victor

+2

Bạn nên đăng những ý tưởng đó và những gì bạn đã viết cho đến nay để giải quyết vấn đề. – chazsolo

+1

Bản sao có thể có của [Cách nhóm mảng đối tượng theo khóa] (https: // stackoverflow.com/questions/40774697/how-to-group-array-of-objects-by-key) –

Trả lời

4

Sử dụng Array#reduce với một đối tượng helper:

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

Bạn cũng có thể đạt được nó bằng cách sử ES6 Bản đồ và lây lan cú pháp:

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

Bạn nên sử dụng bản đồ:

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 

Hoặc:

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

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

đây chỉ là một cấu trúc dữ liệu khác nhau, nhưng chiến lược nhóm theo cách tôi cần là gì? –

+1

@ V.Sambor làm cho các đối tượng của một chìa khóa lớp nhà và phòng mảng có chứa các đối tượng phòng nó có giá trị. –

+1

Cảm ơn sự giúp đỡ của bạn, tôi sẽ thử điều này, hãy quay lại ngay! :) –

1

Tùy thuộc vào nếu bạn muốn bảo vệ dữ liệu ban đầu hay không sẽ ảnh hưởng đến dung dịch. Tôi đã giả sử bạn muốn giữ vật thể ban đầu và tạo một vật thể mới.

Bạn có thể làm điều này trong một vòng lặp nếu bạn sử dụng đối tượng Map để ghi nhớ nơi có nhà ở hiện tại ở đó id thuộc tính. Nếu ngôi nhà đã được đưa vào kết quả, bạn chỉ cần thêm phòng mới. Nếu không, bạn cần phải tạo một đối tượng ngôi nhà mới và lưu trữ chỉ mục của nó trong bản đồ.

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

Các vấn đề liên quan