【问题标题】:Sum values for multiple objects in the array数组中多个对象的总和值
【发布时间】:2021-03-15 06:57:12
【问题描述】:

这就是我所拥有的:

const arrayA = [{name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'},
                {name:'a', amount: 9, test:'FAIL'}, 
                {name:'b', amount: 15, serviceId: '23b', test:'SUCCESS'}]

 

(注意有些对象没有'serviceId')

我想得到:

 [{name:'a', amount: 19, test:'FAIL'},
  {name:'b', amount: 15, test:'SUCCESS'}]
  • 我想对按名称分组的 amount 字段求和。
  • 如果有任何对象的值为FAIL(按名称分组),则'test'字段应为FAIL
  • 我不关心serviceId 的值,也不想将它包含在新对象中。

我已经搜索过,并尝试过这样的事情: (参考:https://stackoverflow.com/a/50338360/13840216

const result = Object.values(arrayA.reduce((r, o) => (r[o.name]
  ? (r[o.name].amount += o.amount)
  : (r[o.name] = {...o}), r), {}));

但仍不确定如何分配test 字段。

任何帮助将不胜感激!

【问题讨论】:

    标签: javascript typescript reduce


    【解决方案1】:

    如有必要,您需要检查test 并更新值。

    const
        array = [{ name: 'a', amount: 10, serviceId: '23a', test: 'SUCCESS' }, { name: 'a', amount: 9, test: 'FAIL' }, { name: 'b', amount: 15, serviceId: '23b', test: 'SUCCESS' }],
        result = Object.values(array.reduce((r, { name, amount, test }) => {
            if (!r[name]) r[name] = { name, amount: 0, test };
            r[name].amount += amount;
            if (test === 'FAIL') r[name].test = 'FAIL';
            return r;
        }, {}));
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案2】:

      这个?只需测试 .test 是否已经失败

      const arrayA = [{ name: 'a', amount: 10, serviceId: '23a', test: 'SUCCESS' }, { name: 'a', amount: 9, test: 'FAIL' }, { name: 'b', amount: 15, serviceId: '23b', test: 'SUCCESS' }],
        result = Object.values(
          arrayA.reduce((r, o) => {
            r[o.name] ? (r[o.name].amount += o.amount) : (r[o.name] = { ...o })
            r[o.name].test = r[o.name].test === "FAIL" ? "FAIL" : o.test;
            return r;
          }, {})
        );
      
      console.log(result);

      【讨论】:

        【解决方案3】:

        将总和和最终值存储在一个对象中,然后将它们转换为数组。

        const arrayA = [
          { name: "a", amount: 10, serviceId: "23a", test: "SUCCESS" },
          { name: "a", amount: 9, test: "FAIL" },
          { name: "b", amount: 15, serviceId: "23b", test: "SUCCESS" },
        ];
        
        const map = {};
        
        arrayA.forEach((row) => {
          if (!map[row.name]) {
            map[row.name] = { name: row.name, amount: 0, test: "SUCCESS" };
          }
        
          map[row.name].amount += row.amount;
        
          if (row.test === "FAIL") {
            map[row.name].test = "FAIL";
          }
        });
        
        const result = Object.values(map);
        
        console.log(result);

        【讨论】:

        • Reduce 消除了分配对象然后运行值的需要 - 你仍然循环两次,但我删除了 downvote
        【解决方案4】:

        这是如何在 js 中处理数据的一个很好的用例,尤其是像 mapreduce 这样的函数如何帮助您进行处理。这是循环和迭代的一个很好的替代方案。

        此外,我建议您按照说明中的定义分步进行处理。例如:

        const arrayA = [
            {name:'a', amount: 10, serviceId: '23a', test:'SUCCESS'},
            {name:'a', amount: 9, test:'FAIL'},
            {name:'b', amount: 15, serviceId: '23b', test:'SUCCESS'}
        ]
        
        // First group the items by name
        const byName = arrayA.reduce((ob, item) => {
            if(!(item.name in  ob))
                ob[item.name] = []
            ob[item.name].push({amount: item.amount, test: item.test})
            return ob
        }, {})
        
        // Then compute the total amount in each group and find if there is any FAIL in a group
        const sumByName = Object.keys(byName).map(name => { // This is a way to iterate through the groups
            // Sum the amount in all elements of a group
            const amount = byName[name].reduce((sum, item) => sum + item.amount , 0)
            // Find if there is any FAIL in a group
            const test = byName[name].map(item => item.test) // Get an array with only the test string
                .includes('FAIL') ? 'FAIL': 'SUCCESS' // Evaluate if the array includes FAIL
            return ({name, amount, test})
        })
        
        console.log(sumByName)

        最后,我建议您在地图上观看这些视频并减少(以及该频道的所有内容)

        【讨论】:

          【解决方案5】:

          你可以使用Array.reduce方法:

          const arrayA=[{name:"a",amount:10,serviceId:"23a",test:"SUCCESS"},{name:"a",amount:9,test:"FAIL"},{name:"b",amount:15,serviceId:"23b",test:"SUCCESS"}];
          
          let result  = arrayA.reduce((aac,{name,amount,test}) => {
              let idx = aac.findIndex(n => n.name === name)
              if( idx != -1){
                  aac[idx].amount += amount;
                  if(test === "FAIL")
                      aac[idx].test = "FAIL"        
                  return aac
              }
              aac.push({name,amount,test})
              return aac
          },[])
          
          console.log(result);
          console.log(arrayA)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-05-25
            • 2016-09-25
            • 1970-01-01
            • 2020-11-07
            • 2020-01-01
            • 2014-04-14
            相关资源
            最近更新 更多