首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并具有相同属性的数组对象

合并具有相同属性的数组对象
EN

Stack Overflow用户
提问于 2018-02-02 15:24:39
回答 2查看 98关注 0票数 0

我正在做我的前端项目之一,我有一种情况,我必须合并/添加对象在数组中存在的一些条件。条件是

  • 只有具有相同标签的对象才应该合并。
  • 对于具有相同标签的对象,如果对象'a‘具有b对象中的属性,则必须添加值,否则只需复制属性。

所以我的意见是

代码语言:javascript
复制
[
  {
    label: 'label-1',
    published: 1,
    draft: 2,
    id: 'some1'
  },
  {
    label: 'label-1',
    published: 2,
    status: 0,
    draft: 1,
    id: 'some4'
  },
  {
    label: 'label-2',
    published: 1,
    draft: 14,
    id: 'some2'
  },
  {
    label: 'label-2',
    published: 12,
    status: 0,
    draft: 14,
    id: 'some3'
  }
]

以及期待

代码语言:javascript
复制
    [
      {
        label: 'label-1',
        published: 3,
        draft: 4,
        status: 0
      },
{
        label: 'label-2',
        published: 13,
        draft: 28,
        status: 0
      }
    ]

目前,我正在使用以下代码来实现相同的目标,但发现它不整洁。有什么办法可以轻易做到这一点。

代码语言:javascript
复制
function mapData(data) {
    let groupData = _.groupBy(data, 'label');
    let stackBarData = [];
    Object.keys(groupData).forEach((key) => {
      if (groupData[key] && groupData[key].length > 0) {
        let temp = Array.from(groupData[key]).reduce((a, b) => {
          for (let property in b) {
            if (b.hasOwnProperty(property)) {
              if (property !== 'label' && property !== 'id' && property !== 'Others') {
                a[property] = (a[property] || 0) + b[property];
              } else {
                a[property] = b[property];
              }
            }
          }
          return a;
        }, {});
        stackBarData.push(temp);
      }
    });
    return stackBarData;
  }

请帮帮忙。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-02 16:00:48

下面是一个纯粹的ES6函数,它收集数值的对象值,并将它们相加(这就是您似乎要做的),每个唯一的标签:

代码语言:javascript
复制
function mapData(data) {
    const grouped = new Map(data.map( ({label}) => [label, { label }] ));
    for (let obj of data) {
        let target = grouped.get(obj.label);
        for (let [key, val] of Object.entries(obj)) {
            if (typeof val === 'number') {
                target[key] = (target[key] || 0) + val;
            }
        }
    }
    return [...grouped.values()];
}

// Sample data
const data = [{label: 'label-1',published: 1,draft: 2,id: 'some1'},{label: 'label-1',published: 2,status: 0,draft: 1,id: 'some4'},{label: 'label-2',published: 1,draft: 14,id: 'some2'},{label: 'label-2',published: 12,status: 0,draft: 14,id: 'some3'}];

console.log(mapData(data));
代码语言:javascript
复制
.as-console-wrapper { max-height: 100% !important; top: 0; }

如果您有要排除的数值属性,那么最好有一组您感兴趣的显式属性:

代码语言:javascript
复制
const props = new Set(['status', 'published', 'draft']);
// ... etc
//
if (props.has(key)) { 
    target[key] = (target[key] || 0) + val;
}
// ...
票数 2
EN

Stack Overflow用户

发布于 2018-02-02 16:15:18

Lodash

_.groupBy()的标签,_.map()组,并合并每个组使用_.mergeWith(),和_.omit()的id。合并组时,如果当前值是数字,则将当前值和新值之和,如果不返回undefined --如果自定义程序返回未定义的值,则由方法处理合并。

代码语言:javascript
复制
const arr = [{"label":"label-1","published":1,"draft":2,"id":"some1"},{"label":"label-1","published":2,"status":0,"draft":1,"id":"some4"},{"label":"label-2","published":1,"draft":14,"id":"some2"},{"label":"label-2","published":12,"status":0,"draft":14,"id":"some3"}]

const result = _(arr)
  .groupBy('label')
  .map((g) => _.omit(_.mergeWith({}, ...g, (objValue, srcValue) => _.isNumber(objValue) ? objValue + srcValue : undefined), 'id'))
  .value()
  
console.log(result)
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

ES6

使用Array.reduce()迭代数组。在每次迭代中,检查累加器( 地图)是否将标签标记为,如果没有,则添加一个带有标签作为键的空对象。使用关键字迭代当前对象Array.forEach(),忽略id,并对数值进行求和。以获得一个扩展Map.values()的数组

代码语言:javascript
复制
const arr = [{"label":"label-1","published":1,"draft":2,"id":"some1"},{"label":"label-1","published":2,"status":0,"draft":1,"id":"some4"},{"label":"label-2","published":1,"draft":14,"id":"some2"},{"label":"label-2","published":12,"status":0,"draft":14,"id":"some3"}]

const result = [...arr.reduce((m, o) => {
  m.has(o.label) || m.set(o.label, {})
  
  const obj = m.get(o.label)
  
  Object.keys(o).forEach((k) => {
    if(k === 'id') return
    
    obj[k] = typeof o[k] === 'number' ? (obj[k] || 0) + o[k] : o[k]
  })
  
  return m
}, new Map()).values()]
  
console.log(result)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48585817

复制
相关文章

相似问题

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