javascript - 为什么这个递归函数会覆盖第二次调用的值?

标签 javascript reactjs ecmascript-6 functional-programming

抱歉,我的标题是这样的,我什至不知道如何表达这里发生的事情。

我正在 React 中开发一个支持多种货币的费用跟踪程序。所跟踪的费用可以任意深度地嵌套在 JSON 对象中。

entertainment: {
  _values: {
    USD: 23,
    AUD: 5,
  },
  'food & drink': {
    _values: {
      AUD: 83,
    },
    'local bar': {
      _values: {
        AUD: 28,
        USD: 2,
      },
    },
  },
  minigolf: {
    _values: {
      USD: 112,
    },
  }
}

费用可以直接存储金额,但它也可以充当进一步详细的子费用的“父”类别。

为了显示费用的总值(value),我编写了一对函数: sumValues(值)_values 对象数组进行求和(值对象是货币代码和整数的键值存储)

总费用(费用) 返回费用的总值(value)。即它具有的任何_values,+所有 child 费用的totalExpense。

我以为我已经将它们编写为纯函数,但是当递归调用 totalExpense() 时,费用的第一个子项返回错误的总计。

totalExpense(entertainment);
//-> Object { USD: 137, AUD: 116 }

确定

totalExpense(entertainment['food & drink']);
//-> Object { AUD: 111, USD: 2 }

确定

totalExpense(entertainment);
totalExpense(entertainment['food & drink']);
//-> Object { AUD: 139, USD: 4 }

不行

我已经研究这段代码几个小时了,但我怎么也看不出发生了什么:

  sumValues = values => {
    return values.reduce((acc, cur) => {
      for (const currency in cur) {
        acc[currency]
          ? (acc[currency] = acc[currency] + cur[currency])
          : (acc[currency] = cur[currency]);
      }
      return acc;
    });
  };
  totalExpense = expense => {
    const values = [];

    if (expense['_values']) {
      values.push(expense['_values']);
    }

    const subExpenses = Object.keys(expense).filter(child => {
      return child[0] !== '_';
    });

    if (subExpenses.length > 0) {
      for (const subExpense of subExpenses) {
        let subtotal = this.totalExpense(expense[subExpense]);
        values.push(subtotal);
      }
    }

    if (values.length) {
      return this.sumValues(values);
    } else {
      throw Error('No values in this expense');
    }
  };
  render() {
    const entertainment = {
      _values: {
        USD: 23,
        AUD: 5,
      },
      'food & drink': {
        _values: {
          AUD: 83,
        },
        'local bar': {
          _values: {
            AUD: 28,
            USD: 2,
          },
        },
      },
      minigolf: {
        _values: {
          USD: 112,
        },
      },
    };

    console.log(this.totalExpense(entertainment));
    console.log(this.totalExpense(entertainment['food & drink']));
    console.log(this.totalExpense(entertainment['minigolf']));

    return;
  }

最佳答案

问题是您的 reduce 回调的初始值是 values 数组中的第一项,然后您继续分配给该项目:

    acc[currency]
      ? (acc[currency] = acc[currency] + cur[currency])
      : (acc[currency] = cur[currency]);

因此,每次调用 sumValues 时,第一项都会发生变化。相反,提供一个空对象作为 reduce 的初始值:

 sumValues = values => {
    return values.reduce((acc, cur) => {
      for (const currency in cur) {
        acc[currency]
          ? (acc[currency] = acc[currency] + cur[currency])
          : (acc[currency] = cur[currency]);
      }
      return acc;
    }, {});
  };

sumValues = values => {
  return values.reduce((acc, cur) => {
    for (const currency in cur) {
      acc[currency] ?
        (acc[currency] = acc[currency] + cur[currency]) :
        (acc[currency] = cur[currency]);
    }
    return acc;
  }, {});
};
totalExpense = expense => {
  const values = [];

  if (expense['_values']) {
    values.push(expense['_values']);
  }

  const subExpenses = Object.keys(expense).filter(child => {
    return child[0] !== '_';
  });

  if (subExpenses.length > 0) {
    for (const subExpense of subExpenses) {
      let subtotal = this.totalExpense(expense[subExpense]);
      values.push(subtotal);
    }
  }
  if (values.length) {
    return this.sumValues(values);
  } else {
    throw Error('No values in this expense');
  }
};
const entertainment = {
  _values: {
    USD: 23,
    AUD: 5,
  },
  'food & drink': {
    _values: {
      AUD: 83,
    },
    'local bar': {
      _values: {
        AUD: 28,
        USD: 2,
      },
    },
  },
  minigolf: {
    _values: {
      USD: 112,
    },
  },
};

console.log(totalExpense(entertainment));
console.log(totalExpense(entertainment['food & drink']));

关于javascript - 为什么这个递归函数会覆盖第二次调用的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54957021/

相关文章:

javascript - 当数据库值为空时,如何在 xml 标签之间插入空格

reactjs - 如何导入 "useAccordionButton"?

javascript - ReactJs 从组件聚合数据

reactjs - 使用对象剩余删除嵌套对象

javascript - KO Computed 不更新 UI

javascript - promise 不返回 [node.js]

java - 如何在 webapp 中查看我的 index.html 文件,该文件是从 url 上的 swagger ui 克隆的

css - 如何在 React App 中显示 Emoji

javascript - 如何使用 Babel 构建 Webpack(同时保留源文件夹结构)?

javascript - 无法获取类属性的属性描述符