Javascript对象重组与性能

时间:2017-06-23 20:09:59

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

新对象应如下所示:

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,我的对象必须稍微重构,而不仅仅是重新组合。

可能的解决方案(灵感来自@ 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);

4 个答案:

答案 0 :(得分:4)

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);与辅助对象一起使用:

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

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

import re
s = """`Hel"lo` 2* "Hel`lo\""""
print([x.group(2) for x in re.finditer(r"([\"'`])(.*?)\1", s)])

答案 1 :(得分: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

答案 2 :(得分:1)

取决于您是否要保留初始数据会影响解决方案。我以为你想保留原始对象并生成一个新对象。

如果使用Map对象来记住现有房屋所在的id属性,则可以在单个循环中执行此操作。如果房子已经插入到结果中,您只需要添加新房间。否则,您需要创建一个新的house对象并将其存储在地图中。

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

答案 3 :(得分:1)

&#13;
&#13;
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;
  
});
&#13;
&#13;
&#13;