数组操作:合并对象[ES6]

时间:2019-07-16 14:17:18

标签: javascript arrays ecmascript-6

所以我现在已经挣扎了几个小时。这就是我想要做的。

我有一个对象数组:

initArr = [
  {id: 5, time: 100, download: true},
  {id: 2, time: 50, download: false},
  {id: 3, time: 1000, download: true},
  {id: 5, time: 50, download: true},
  {id: 5, time: 550, download: false},
  {id: 2, time: 1500, download: true}
]

某些对象具有相同的id,我想将它们合并在一起。
-但是合并时,我想将两个合并对象的time值相加。
-如果两个合并对象之一具有download: false,则合并对象应具有false,否则为true

这是我到目前为止的内容(即使考虑下载密钥,我仍然没有开始):

const mergedArr= [];

initArr.map(obj => obj['id'])
     .map((id, i, arr) => {
        if (arr.indexOf(id) === i) {
            mergedArr.push(initArr[i]);
        } else { 
          const mergeIndex = mergedArr.map( x => x.id).indexOf(id);
          mergedArr[mergeIndex].playTime +=initArr[arr.indexOf(id)].playTime;
        }
    return mergedArr
});

我很乐意输入或提示:)

6 个答案:

答案 0 :(得分:2)

您可以reduce阵列。创建一个累加器对象,每个id作为键,合并的对象作为值。如果id已经存在,请用当前对象更新timedownload。否则,添加当前id作为键,并设置当前对象的副本作为其值。然后使用Object.values()从此累加器对象获取一个值数组。

const initArr = [
  { id: 5, time: 100, download: true },
  { id: 2, time: 50, download: false },
  { id: 3, time: 1000, download: true },
  { id: 5, time: 50, download: true },
  { id: 5, time: 550, download: false },
  { id: 2, time: 1500, download: true }
]

const merged = initArr.reduce((acc, o) => {
  if (acc[o.id]) {
    acc[o.id].time += o.time;
    acc[o.id].download = acc[o.id].download && o.download;
  } else
    acc[o.id] = { ...o };

  return acc;
}, {})

console.log(Object.values(merged))

答案 1 :(得分:1)

通过对象的id将数组缩减为Map,然后使用Map.values()Array.from()(或扩展为数组)转换回数组。 / p>

注意:在这种情况下,将Map用作累加器要比使用对象好,因为id属性是数字属性。在ES6中,对象通常保持插入顺序,除非属性为数字。将具有数字属性键的对象转换为数组时,数字属性排在最前面,并按其值排序。另一方面,地图始终保持插入顺序。

const initArr = [
  {id: 5, time: 100, download: true},
  {id: 2, time: 50, download: false},
  {id: 3, time: 1000, download: true},
  {id: 5, time: 50, download: true},
  {id: 5, time: 550, download: false},
  {id: 2, time: 1500, download: true}
]

const result = Array.from(initArr.reduce((r, o) => {
  if(!r.has(o.id)) r.set(o.id, { ...o });
  else {
    const current = r.get(o.id);
    current.time += o.time;
    current.download = current.download && o.download
  }
  
  return r;
}, new Map).values());

console.log(result);

答案 2 :(得分:1)

尝试一下,也支持下载选项

const arr = [
  {id: 5, time: 100, download: true},
  {id: 2, time: 50, download: false},
  {id: 3, time: 1000, download: true},
  {id: 5, time: 50, download: true},
  {id: 5, time: 550, download: false},
  {id: 2, time: 1500, download: true}
]

const result = arr.reduce((res, obj) => {
    const found = res.find(t => t.id === obj.id);

    if(found){
        found.time += obj.time;
        found.download = found.download && obj.download;    
    } else {
        res.push(obj);
    }
    return res;
}, []);

console.log(result);

答案 3 :(得分:0)

您可以将reduce用于:

  • 检查数组是否在每个循环中都有ID为ID的项目
  • 如果有,请添加时间

其他

  • 推物体

const arr = [
  {id: 5, time: 100, download: true},
  {id: 2, time: 50, download: false},
  {id: 3, time: 1000, download: true},
  {id: 5, time: 50, download: true},
  {id: 5, time: 550, download: false},
  {id: 2, time: 1500, download: true}
]

console.log(arr.reduce((a, o) => {
  const i = a.findIndex(({id}) => id === o.id)
  i + 1 ? a[i].time += o.time : a.push(o)
  return a
}, []))

答案 4 :(得分:0)

另一个reduce解决方案:

const initArr = [
  {id: 5, time: 100, download: true},
  {id: 2, time: 50, download: false},
  {id: 3, time: 1000, download: true},
  {id: 5, time: 50, download: true},
  {id: 5, time: 550, download: false},
  {id: 2, time: 1500, download: true}
]

const merged = initArr.reduce((a,c) => {
    const found = a.find(x => x.id === c.id);
    if (found) {
        found.time += c.time;
        found.download = found.download && c.download;
        return a;
    }
    return [...a, {...c}];
}, []);

console.log(merged);

答案 5 :(得分:0)

        function manipulation(initArr){
            var resultArray = [];
            var arrMap = new Map();
            var currIndex = 0;
            initArr.forEach(function(item, index){
                if(arrMap.has(item.id)){
                    var existingItem = resultArray[arrMap.get(item.id)];
                    existingItem.time = item.time+existingItem.time;
                    if(existingItem.download && !item.download){
                        existingItem.download = false;
                    }
                }else{
                    arrMap.set(item.id, currIndex);
                    resultArray.push(item);
                    currIndex++;
                }
            })
            return resultArray;
        }