Javascript对象重组与性能

V. *_*bor 5 javascript arrays filtering javascript-objects

我正在研究一个问题,我必须将一个对象数组从一个表单分组到另一个表单.

一个例子优于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
  },
];
Run Code Online (Sandbox Code Playgroud)

新对象应如下所示:

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" }
      ]
    }
  ]
};
Run Code Online (Sandbox Code Playgroud)

我必须找到所有房间的独特房屋,并从房间内的初始物品中添加每个价格.

我想知道哪个是最好的方法,因为我会有大量的元素?

我有一些关于多个循环的想法,但对我而言,我的解决方案似乎有点过于复杂.

更新:我的问题与复制的候选人不同,因为我不使用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);
Run Code Online (Sandbox Code Playgroud)

Ori*_*ori 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);
Run Code Online (Sandbox Code Playgroud)

您还可以使用 ES6 Map 和 spread 语法来实现它:

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);
Run Code Online (Sandbox Code Playgroud)