【问题标题】:Cumulative sum of specific keys with array output using reduce使用reduce的具有数组输出的特定键的累积和
【发布时间】:2022-01-12 05:39:18
【问题描述】:

假设我有以下数组:

let arr = [{a: 1, b: 2}, {a: 2, b: 4}, {a: 8, b: -1}]

我想计算每个键的累积和,但我也希望输出是一个长度相同的数组,每个步骤的累积值。最终结果应该是:

[{a: 1, b: 2}, {a: 3, b: 6}, {a: 11, b: 5}]

我的问题是我无法根据需要获取数组。我只得到了最终的对象:

let result = arr.reduce((accumulator, element) => {
  if(accumulator.length === 0) {
    accumulator = element
  } else {
    for(let i in element){
      accumulator[i] = accumulator[i] + element[i]
    }
  }
  return accumulator
}, [])

console.log(result); // {a: 11, b: 5}

【问题讨论】:

    标签: javascript object functional-programming


    【解决方案1】:

    给定:

    const xs =
      [ {a: 1, b:  2}
      , {a: 2, b:  4}
      , {a: 8, b: -1}];
    

    定义一个函数sum 如:

    const sum = ([head, ...tail]) =>
      tail.reduce((x, y) =>
        ({a: (x.a+y.a), b: (x.b+y.b)}), head);
    
    sum(xs);
    //=> {a: 11, b: 5}
    

    然后将该函数应用于xs 的较大切片上的映射:

    xs.map((_, i, arr) => sum(arr.slice(0, i+1)));
    //=> [ {a:  1, b: 2}
    //=> , {a:  3, b: 6}
    //=> , {a: 11, b: 5}]
    

    【讨论】:

      【解决方案2】:

      您所追求的听起来像scan() 高阶函数(借用ramda.js 的想法),它允许您返回数组中每个元素的累积结果。 scan 方法类似于.reduce() 方法的行为方式,只是它返回每个元素的累加器。您可以像这样自己构建scan() 函数:

      let arr = [{a: 1, b: 2}, {a: 2, b: 4}, {a: 8, b: -1}];
      
      const scan = ([x, ...xs], fn) => xs.reduce((acc, elem) => {
        return [...acc, fn(acc.at(-1), elem)];
      }, xs.length ? [x] : []);
      
      const res = scan(arr, (x, y) => ({a: x.a+y.a, b: x.b+y.b}));
      console.log(res);

      您可能会考虑进一步改进,例如为扫描方法提供初始值(类似于 reduce 接受的方式)。另外,如果您需要更好的浏览器支持,.at() 方法目前对浏览器的支持有限,因此您可以考虑创建自己的 at() 函数:

      const at = (arr, idx) => idx >= 0 ? arr[idx] : arr[arr.length + idx];
      

      【讨论】:

        【解决方案3】:

        这里有一个更简洁的 reduce,结果可能不那么可读......

        array.reduce((y,x,i) => ( i===0 ? y : [...y, {a: x.a + y[i-1].a, b: x.b + y[i-1].b}]),[array[0]])
        

        let array = [{a: 1, b: 2}, {a: 2, b: 4}, {a: 8, b: -1}]
        let culm = array.reduce((y,x,i) => ( i===0 ? y : [...y, {a: x.a + y[i-1].a, b: x.b + y[i-1].b}]),[array[0]])
        console.log(culm)
         

        【讨论】:

          【解决方案4】:

          您可以使用reduce as 轻松实现结果

          let arr = [
            { a: 1, b: 2 },
            { a: 2, b: 4 },
            { a: 8, b: -1 },
          ];
          
          const result = arr.reduce((acc, curr, i) => {
            if (i === 0) acc.push(curr);
            else {
              const last = acc[i - 1];
              const newObj = {};
              Object.keys(curr).forEach((k) => (newObj[k] = curr[k] + last[k]));
              acc.push(newObj);
            }
            return acc;
          }, []);
          
          console.log(result);

          【讨论】:

            【解决方案5】:

            类似这样的:

            const arr = [{a: 1, b: 2}, {a: 2, b: 4}, {a: 8, b: -1}]
            
            const result = arr.reduce((accumulator, element, index) => {
              if(accumulator.length === 0) {
                accumulator.push(element)
              } else {
                const sum = {};
                for(let i in element) {
                  sum[i] = element[i] + (accumulator[index - 1][i] || 0)
                }
                accumulator.push(sum)
              }
              return accumulator
            }, [])
            
            console.log(result);

            另一个选项是使用Map 保持求和结果,如果数组元素中的键并不总是相同,它会有所帮助。

            const arr = [{a: 1, b: 2}, {a: 2}, {a: 8, b: -1}];
            const map = new Map();
            const result = arr.map((element) => {
              const sum = {};
              for (let i in element) {
                sum[i]= element[i] + (map.get(i) || 0);
                map.set(i, sum[i]);
              }
              return sum;
            });
            
            console.log(result);

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-04-15
              • 2023-01-20
              • 2020-08-11
              • 1970-01-01
              • 2022-11-16
              • 1970-01-01
              • 1970-01-01
              • 2021-11-27
              相关资源
              最近更新 更多