使用.reduce对基于对象枚举的对象变量进行求和



我正在尝试使用.reduce方法来计算不同Expense对象的金额。这些Expenses可以是不同类型的,我想保持数组中的对象被它分割。例如,以下一系列费用:

[
  {type: A, amount: 2},
  {type: A, amount: 1},
  {type: B, amount: 2},
  {type: A, amount: 3},
  {type: C, amount: 2},
  {type: B, amount: 1}
]

应该变成这样:

[
  {type: A, amount: 6},
  {type: B, amount: 3},
  {type: C, amount: 2}
]

还要注意,如果不存在该类型的费用,则不应存在金额:0,而应减去一笔费用。因此,如果没有C类费用,结果应该是:

[
  {type: A, amount: 6},
  {type: B, amount: 3}
]

这就是我所走的路:

    private joinExpenses(expenses: Expense[]): Expense[] {
    // Add all expenses amount splitted by payment type and store in object
    const expenseArrayAsObject = expenses.reduce(
        (expensesObject, item) => {
            const type = item.type;
            if (!expensesObject.hasOwnProperty(type)) {
                expensesObject[type] = {
                    type: type,
                    amount: {
                        amount: 0
                    } as Money
                } as Expense;
            }
            const expense: Expense = expensesObject[type];
            expense.amount.amount = expense.amount.amount + item.amount.amount;
            expensesObject[type] = expense;
            return expensesObject;
        },
        {} as { [key: string]: any }
    );
    // Convert object to array
    const joinedExpenses: Expense[] = [];
    for (const key in expenseArrayAsObject) {
        joinedExpenses.push(expenseArrayAsObject[key]);
    }
    return joinedExpenses;
}

这是可行的,但我觉得首先映射到对象并将其转换为数组是一个太多的步骤,而且可以简化。之后我可以进行一些操作,但我觉得我在数组中迭代太多了。。我就是不知道怎么做。你能帮我吗?

您可以将以下内容与.reduce().find()组合使用:

const data = [
  {type: 'A', amount: 2},
  {type: 'A', amount: 1},
  {type: 'B', amount: 2},
  {type: 'A', amount: 3},
  {type: 'C', amount: 2},
  {type: 'B', amount: 1}
];
const result = data.reduce((a, c) => {
  const found = a.find(e => e.type === c.type);
  if (found) found.amount = found.amount + c.amount;      
  return found ? a : a.concat(c);
}, []);
console.log(result);

这就是您需要的吗?

const array = [
    {type: 'A', amount: 2},
    {type: 'A', amount: 1},
    {type: 'B', amount: 2},
    {type: 'A', amount: 3},
    {type: 'C', amount: 2},
    {type: 'B', amount: 1}
];
const result = array.reduce((acc, item) => {
    const current = acc.find(el => el.type === item.type);
    if(!current) {
        acc.push(item)
    }else{
        current.amount += item.amount;
    }
    return acc;
}, []);
console.log(result);

reduce回调中,使用findIndex检查累加器accray中是否存在具有相同键的对象。然后更新金额的值,否则创建对象

let data = [{
    type: 'A',
    amount: 2
  },
  {
    type: 'A',
    amount: 1
  },
  {
    type: 'B',
    amount: 2
  },
  {
    type: 'A',
    amount: 3
  },
  {
    type: 'C',
    amount: 2
  },
  {
    type: 'B',
    amount: 1
  }
]
let newData = data.reduce((acc, curr) => {
  let ifKeyExist = acc.findIndex((item) => {
    return item.type === curr.type;
  });
  if (ifKeyExist === -1) {
    acc.push({
      type: curr.type,
      amount: curr.amount
    });
  } else {
    acc[ifKeyExist].amount += curr.amount;
  }
  return acc;
}, []);
console.log(newData)

reduce使用对象作为累加器。使用type作为键,并为其分配新对象。然后使用Object.values获取所需的输出。

const data = [
  {type: 'A', amount: 2},
  {type: 'A', amount: 1},
  {type: 'B', amount: 2},
  {type: 'A', amount: 3},
  {type: 'C', amount: 2},
  {type: 'B', amount: 1}
];
const out = Object.values(data.reduce((acc, { type, amount }) => {
  // If type doesn't exist as a key on the accumulator
  // add it and set its value to a new object
  acc[type] = acc[type] || { type, amount: 0 };
  // Increment the object amount value
  acc[type].amount += amount;
  // Return the accumulator
  return acc;
}, {}));
console.log(out);

相关内容

  • 没有找到相关文章

最新更新