从对象数组中创建新的对象,包含唯一元素。

4

我有一个对象数组,每个对象都有一些键值对。其中一个键值对(例如“obj”)也是对象数组。

例如:

const arrOfObj = [
  { 
    "id": 1
    "obj": {
      "arr1": ["arr1-1"],
      "arr2": ["arr2-1", "arr2-2"],
      "arr3": ["arr3-1", "arr3-2"]
    }
  },
  { 
    "id": 1
    "obj": {
      "arr1": ["arr1-2"],
      "arr2": ["arr2-1", "arr2-3"],
      "arr3": ["arr3-1", "arr3-3"],
      "arr4": ["arr4-1"],
    }
  },
];

我需要获取一个新的“obj”对象,其中包含唯一的键和其中唯一的元素。

需要的示例:

const newObj = {
   "arr1": ["arr1-1", "arr1-2"],
   "arr2": ["arr2-1", "arr2-2", "arr2-3"],
   "arr3": ["arr3-1", "arr3-2", "arr3-3"],
   "arr4": ["arr4-1"],
}

所有这些都是通过API动态请求获取的,所以我不知道这些键值对的名称,但我需要将它们存储。

我有解决方案,但我是JavaScript的新手,想知道如何简化和改进我的代码

1. 首先,我定义一个新对象,并从“arrOfObj”中检索出其键对应的名称。

let filterObj = {};

arrOfObj.forEach(function (item) {
  for (let key in item.obj) {
    filterObj[key] = [];
  }
});

2. 然后我从"arrOfObj"获取每个数组的所有元素,并将它们存储在新对象"filterObj"中,与相同名称的键值对一起。

arrOfObj.forEach(function (item) {
  for (let key in item.obj) {
    for (let element = 0; element < item.obj[key].length; element++) {
      filterObj[key].push(item.obj[key][element]);
    }
  }
});

3. 最后,我在过滤数组时只保留唯一元素。

for (let key in filterObj) {
  filterObj[key] = Array.from(new Set(filterObj[key]));
}

它能够正常工作,我得到了我想要的,但它看起来非常庞大。如何以最简单的方式简化这段代码呢?

感谢帮助与建议。


1
总体来说,你的代码还不错,也不是意大利面条式编程。每一步都很容易理解。虽然有一些快捷方式,比如迭代Object.entries(),但像你这样手写所有代码也是一个很好的学习经验。 - charlietfl
@charlietfl 谢谢 :) 但我想提高我的JS技能,我完全确定所有这些都可以和必须以更简单更好的方式编写... - Agatha
1
“Much simpler”...有一些技巧可以将其简化,但如果不像当前代码那样清晰易读和易于维护,则可能会使其难以阅读。一个建议是在第二步中使用forEach()而不是更冗长的for循环。 - charlietfl
1
并且了解一下 Object.keys()Object.values()Object.entries() 的工作原理。 - charlietfl
@HereticMonkey 不是很准确。我需要的比简单的.merge方法要复杂一些。无论如何,谢谢您 ^-^ - Agatha
显示剩余2条评论
2个回答

1

使用Object#fromEntriesArray#reduceObject#entriesArray#forEachSetMap的另一种解决方案:

const arrOfObj = [ { "id": 1, "obj": { "arr1": ["arr1-1"], "arr2": ["arr2-1", "arr2-2"], "arr3": ["arr3-1", "arr3-2"] } }, { "id": 1, "obj": { "arr1": ["arr1-2"], "arr2": ["arr2-1", "arr2-3"], "arr3": ["arr3-1", "arr3-3"], "arr4": ["arr4-1"] } } ];

const filterObj = 
  // transform the resulting list of key-values pairs to an object at the end
  Object.fromEntries(
    // get a map of array name as key and its unique items as value
    [...arrOfObj.reduce((map, { obj = {} }) => {
      // iterate over current element's object to update the map
      Object.entries(obj).forEach(([currentKey, currentValues]) => {
        const keyValues = [...(map.get(currentKey) || []), ...currentValues];
        map.set(currentKey, [...new Set(keyValues)]);
      });
      return map;
    }, new Map)]
  );

console.log(filterObj);


@Agatha 没有关系。请确保阅读文档以获得更好的理解! - Majed Badawi

1
你可以使用一些解构和Object.entries()和Object.keys()来简化这个过程,并将所有操作都应用于新对象。

const newObj  = {}

arrOfObj.forEach(({obj}) => {
    Object.entries(obj).forEach(([k, arr]) => {
       newObj[k] = newObj[k] || [];
       newObj[k].push(...arr);
    })
});

Object.keys(newObj).forEach(k => newObj[k] = [...new Set(newObj[k])]);

console.log(newObj)
<script>
const arrOfObj=[{id:1,obj:{arr1:["arr1-1"],arr2:["arr2-1","arr2-2"],arr3:["arr3-1","arr3-2"]}},{id:1,obj:{arr1:["arr1-2"],arr2:["arr2-1","arr2-3"],arr3:["arr3-1","arr3-3"],arr4:["arr4-1"]}}];
</script>


非常优雅。我从这个片段中学到了很多新东西,谢谢 ^-^ - Agatha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接