【问题标题】:How to create an accumulation variable within javascript mapping function如何在javascript映射函数中创建累积变量
【发布时间】:2021-06-22 21:26:53
【问题描述】:

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

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

<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>

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

【问题讨论】:

    标签: javascript html reactjs html-table mapping


    【解决方案1】:

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

    {
        (() => {
            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)
    ));
    

    【讨论】:

    • 非常感谢!!您包含的所有这些返回语句和语法规则对我来说似乎很混乱,并且超出了我的范围(但是它确实工作得很好!)。您是否熟悉任何可以解释所有这些看起来很奇怪的语法的资源?
    • IIFE (() =&gt; { })() 用于创建一个可以在其中声明变量的范围。需要这样才能初始化 let debit = 0;,否则无法创建滚动值。 stackoverflow.com/questions/8228281/…我不确定你指的是什么其他奇怪的语法。
    【解决方案2】:

    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>)
    )}
    

    【讨论】:

      猜你喜欢
      • 2019-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多