js 把数组的多个对象合并成一个对象,key相同的,把value合并成数组,怎么做?

js 把数组的多个对象合并成一个对象,key相同的,把value合并成数组,怎么做?

    //原数据
    list = [
        {
          brand: "Hisense1",
          name: "C Series",
          type: "多联机和新风机通用室外机",
          photo: "",
          minRatio: 0.5,
          maxRatio: 1.3,
          alarmMaxRatio: 0,
          isOnmarket: true,
          isDefault: false,
          DWGFile: "",
          pictureFile: "",
          remarks: "",
          id: "b53d408d-c4f9-4751-86a0-37751c48c6ad",
        },
        {
          brand: "Hisense2",
          name: "C Series",
          type: "多联机和新风机通用室外机",
          photo: "",
          minRatio: 0.5,
          maxRatio: 1.3,
          alarmMaxRatio: 0,
          isOnmarket: true,
          isDefault: false,
          DWGFile: "",
          pictureFile: "",
          remarks: "",
          id: "b53d408d-c4f9-4751-86a0-37751c48c6ad",
        },

        //想要的数据
        listFilters = 
            {
                brand: ["Hisense1", "Hisense2"],
                name: ["C Series", "B Series"],
                type: ["多联机和新风机通用室外机1", "多联机和新风机通用室外机2"],
                ...
            }

因为我想要的数据结构有点变化:

listFilters = 
            {
                brand: [{text:"Hisense1",value:"Hisense1"}, {text:"Hisense2",value:"Hisense2"}],
                ...
            }

最后我用的方法是:

for (let i = 0; i < this.list.length; i++) {
        for (let key in this.list[i]) {
          if (this.listFilters.hasOwnProperty(key)) {
            //如果已经有属性名称,则追加值
            let flag = false;
            for (let j = 0; j < this.listFilters[key].length; j++) {
              if (this.listFilters[key][j].value === this.list[i][key]) {
                flag = true;
              }
            }
            if (!flag) {
              //如果属性值不相同时追加
              this.listFilters[key].push({
                text: this.list[i][key],
                value: this.list[i][key],
              });
            }
          } else {
            //如果没有属性名称则添加key:value
            this.listFilters[key] = [
              { text: this.list[i][key], value: this.list[i][key] },
            ];
          }
        }
      }
阅读 8k
3 个回答

Array.prototype.reduce 是个好东西:

直接看代码:

const mergedObject = list.reduce(
  (target, item) => ({
    ...target,
    ...Object.keys(item).reduce(
      (object, key) => ({
        ...object,
        [key]: Array.isArray(target[key])
          ? target[key].concat(item[key])
          : target.hasOwnProperty(key)
          ? [target[key], item[key]]
          : item[key],
      }),
      {}
    ),
  }),
  {}
);

每一步的说明:

const mergedObject = list.reduce(
  // target: 目录对象, item: 当前遍历到的元素(对象)
  (target, item) => ({
    // 先将目录对象已经取得的值全部赋予新目录对象
    ...target,
    // 拿到 item 的 key 列表,并且通过该列表去创建一个新的对象
    ...Object.keys(item).reduce(
      // 新的对象,以及 item 中的一个 key
      (object, key) => ({
        // 新对象先把已有的属性全部加上
        ...object,
        // 设定当前的 key 对应的值
        [key]: Array.isArray(target[key])
          ? target[key].concat(item[key]) // 如果当前的 key 在 target[key] 中是数组,则表示已经存在超过两个具有该 key 的对象了,所以直接将新值  concat 进去即可
          // : target[key] // 否则的话,判断 target[key] 上面是否已经存在该值了
          : target.hasOwnProperty(key) // 更新一下,需要拿 `hasOwnProperty` 判断,否则如果值为 0, false, undefined 等,都会被判错
          ? [target[key], item[key]] // 如果存在了该值,则将该值变成一个数组(因为已经有两个了)
          : item[key], // 否则的话,就把当前这个值赋值给 target
      }),
      {}
    ),
  }),
  {}
);

数组与对象之间进行相互转换的过程中, Array.prototype.reduce 用好了,事半功倍,不要说这样的代码难看懂,如果思维清楚,这样的代码从头看到尾应该是很容易知道运行结果的。

运行结果:

{
  "brand": [
      "Hisense1",
      "Hisense2"
  ],
  "name": [
      "C Series",
      "C Series"
  ],
  "type": [
      "多联机和新风机通用室外机",
      "多联机和新风机通用室外机"
  ],
  "photo": "",
  "minRatio": [
      0.5,
      0.5
  ],
  "maxRatio": [
      1.3,
      1.3
  ],
  "alarmMaxRatio": 0,
  "isOnmarket": [
      true,
      true
  ],
  "isDefault": false,
  "DWGFile": "",
  "pictureFile": "",
  "remarks": "",
  "id": [
      "b53d408d-c4f9-4751-86a0-37751c48c6ad",
      "b53d408d-c4f9-4751-86a0-37751c48c6ad"
  ]
}

image.png

console.time();
 //原数据
    var list = [
        {
          brand: "Hisense1",
          name: "C Series",
          type: "多联机和新风机通用室外机",
          photo: "",
          minRatio: 0.5,
          maxRatio: 1.3,
          alarmMaxRatio: 0,
          isOnmarket: true,
          isDefault: false,
          DWGFile: "",
          pictureFile: "",
          remarks: "",
          id: "b53d408d-c4f9-4751-86a0-37751c48c6ad",
        },
        {
          brand: "Hisense2",
          name: "C Series",
          type: "多联机和新风机通用室外机",
          photo: "",
          minRatio: 0.5,
          maxRatio: 1.3,
          alarmMaxRatio: 0,
          isOnmarket: true,
          isDefault: false,
          DWGFile: "",
          pictureFile: "",
          remarks: "",
          id: "b53d408d-c4f9-4751-86a0-37751c48c6ad",
        }]
list.reduce((acc,cur)=>(Object.entries(cur).forEach(([key,val])=>(acc[key]||=[]).push(val)),acc),{});
console.timeEnd();
// 0.08203125 ms

思路和楼上一样,不过这个是简写的,楼上 es6 的... 解构也耗性能。

var listFilters = {};
for (var i = 0; i < list.length; ++i) {
    var obj = list[i];
    for (var key in obj) {
        if (listFilters.hasOwnProperty(key)) {
            if (!(listFilters[key] instanceof Array)) {
                listFilters[key] = [listFilters[key]];
            }
            listFilters[key].push(obj[key]);
        } else {
            listFilters[key] = obj[key];
        }
    }
}
console.log(listFilters);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏