首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数组操作:合并对象[ES6]

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

Stack Overflow用户
提问于 2019-07-16 14:17:18
回答 6查看 109关注 0票数 2

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

我有一组对象:

代码语言:javascript
复制
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

到目前为止(我甚至还没有开始考虑下载键):

代码语言:javascript
复制
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
});

我喜欢这样的输入或提示:)

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2019-07-16 14:22:06

通过对象的地图将数组还原为id,然后使用Map.values()Array.from() (或扩展到数组)将数组转换回数组。

注意:在这种情况下,使用Map作为累加器比使用对象更好,因为id属性是数字的。在ES6中,对象通常保持插入顺序,除非属性是数字的。当具有数字属性键的对象被转换为数组时,首先是数字属性,并根据它们的值排序。另一方面,Map总是保持插入的顺序。

代码语言:javascript
复制
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);

票数 1
EN

Stack Overflow用户

发布于 2019-07-16 14:24:08

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

代码语言:javascript
复制
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))

票数 2
EN

Stack Overflow用户

发布于 2019-07-16 14:39:04

试试这个,也支持下载选项。

代码语言:javascript
复制
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);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57059409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档