如何在 javascript 映射函数中创建累积变量

How to create an accumulation variable within javascript mapping function

我在 React 中创建了一个 table。我使用 javascript 来映射包含呈现动态 table 所需的所有信息的对象。我的几个列包含数字,我想将这些列相加到附加列中的给定点。下面是我的 table.

的例子

我们的想法是,余额栏将汇总截至该点的整个借方栏。所以第一行的余额单元格应该显示 50(就像它一样)。但是,余额栏中的第二个单元格需要说 100(截至该点的借方栏中所有单元格的总和)。这是我用来映射对象(存储在状态中)以填充 table 的反应代码。请注意,余额列未存储在对象中...我试图以某种方式在映射函数中创建此列值。

<table id="transactionDetailDisplay">
        <tr>
            <th>#</th>
            <th>Account</th>
            <th>Description</th>
            <th>Debit</th>
            <th>Credit</th>
            <th>Balance</th>
            </tr>       
    {this.state.transactionObject.map((item =>
        <tr>
            <td>{}</td>
            <td>{item.AccountID}</td>
            <td>{item.Description}</td>
            <td>{item.Debit}</td>
            <td>{item.Credit}</td>
            <td>{item.Debit}</td>
        </tr>))}
    </table>

我想做的是在我的地图函数中添加一个变量作为累加器。例如,我不想将最后一个 table 数据项表示为 item.Debit,而是想将 item.Debit 存储在一个变量中,然后将该变量值放入 table 数据行.在映射函数的每个循环中,我都会将 item.Debit 添加到变量以累积要在 Balance 中显示的正确总和。但是,我无法找出正确的 javascript 来在映射函数和/或 table 标记中创建变量累加器。我认为因为它在 table 标记内,所以我不能像在其他地方那样定义一个变量。有没有办法可以做到这一点,也许用特殊的语法?有谁知道有什么技巧可以帮助我吗?非常感谢任何想法!!

您可以预先创建一个变量,然后添加到地图回调中。

{
    (() => {
        let debit = 0;
        return this.state.transactionObject.map((item) => {
            debit += item.Debit;
            return (
                <tr>
                    <td>{ }</td>
                    <td>{item.AccountID}</td>
                    <td>{item.Description}</td>
                    <td>{item.Debit}</td>
                    <td>{item.Credit}</td>
                    <td>{debit}</td>
                </tr>);
        })
    })()
}

您还可以考虑在渲染之前创建一个借方数组。

let debit = 0;
const debits = this.state.transactionObject.map(item => debit += item.debit);
{
    this.state.transactionObject.map((item, i) =>
        <tr>
            <td>{ }</td>
            <td>{item.AccountID}</td>
            <td>{item.Description}</td>
            <td>{item.Debit}</td>
            <td>{item.Credit}</td>
            <td>{debits[i]}</td>
        </tr>
    )
}

您可以通过将数组切片到该点并将其相加来使其发挥作用,但这会增加 O(n ^ 2) 的复杂性。

const debits = this.state.transactionObject.map((_, i, arr) => (
    arr.slice(0, i + 1).reduce((a, b) => a + b)
));

Array.prototype.map 函数回调应该是 纯函数 ,即没有像改变余额值这样的副作用。使用 Array.prototype.reduce 将数组缩减为单个值。

const balance = this.state.transactionObject.reduce(
  (balance, { Debit }) => balance + Debit,
  0,
);

如果您需要计算多个总计,您可以减少到一个具有不同属性的对象来表示您需要的总计,这样您仍然只需迭代数组一次来计算它们。

编辑

我想我最初误解了你的要求,你想显示到当前行为止的累计余额。

首先预先计算每行的余额。

const arr = this.state.transactionObject.map((item, index, arr) => ({
  ...item,
  Balance: arr[index - 1]?.Balance ?? 0) + item.Debit ?? 0
}));

...

{arr.map((item =>
  <tr>
    <td>{}</td>
    <td>{item.AccountID}</td>
    <td>{item.Description}</td>
    <td>{item.Debit}</td>
    <td>{item.Credit}</td>
    <td>{item.Balance}</td>
  </tr>)
)}