Android中如何在Kotlin数据类中用Fold计算交易前后余额
嘿,这个需求用fold完全能搞定,思路其实很清晰——我们要从账户的初始余额出发,顺着每笔交易的先后顺序,一步步算出每笔交易前后的余额,同时把结果填充到对应的TransactionEntity里。
核心思路
fold的本质是维护一个累加状态,这里我们的状态就是「当前账户余额」。遍历每笔交易时,我们用这个状态给TransactionEntity赋值balanceBefore,然后根据交易金额计算出新的余额作为balanceAfter,再把新余额作为下一次遍历的状态即可。
具体实现代码
先给你一个完整的转换函数,包含从Account到AccountEntity的全流程:
import java.math.BigDecimal import java.text.SimpleDateFormat fun Account.toAccountEntity(): AccountEntity { // 1. 把初始余额从字符串转成BigDecimal,作为计算的起点 val initialBalance = balance.toBigDecimal() // 2. 先把原始Transaction转成基础的TransactionEntity(暂不填充余额字段) // 注意:一定要先按日期排序,确保交易是按时间先后处理的,否则余额计算会出错! val baseTransactionEntities = transactions.sortedBy { it.date } .map { transaction -> TransactionEntity( amount = transaction.amount.toBigDecimal(), balanceBefore = BigDecimal.ZERO, // 先占位,后续用fold更新 balanceAfter = BigDecimal.ZERO, description = transaction.description, otherAccount = transaction.otherAccount, date = SimpleDateFormat("yyyy-MM-dd").parse(transaction.date) // 按你的日期格式调整 ) } // 3. 用fold处理余额计算 val processedTransactions = baseTransactionEntities .fold(mutableListOf<TransactionEntity>() to initialBalance) { (processedList, currentBalance), entity -> // 给当前交易设置「交易前余额」 entity.balanceBefore = currentBalance // 计算「交易后余额」:这里要注意金额的正负规则,比如收入为正、支出为负,根据你的业务调整 val newBalance = currentBalance.add(entity.amount) entity.balanceAfter = newBalance // 返回新的状态:已处理的交易列表 + 更新后的余额 processedList.apply { add(entity) } to newBalance } .first // 取出最终的交易列表 // 4. 组装成最终的AccountEntity return AccountEntity( account = account, balance = balance, transactions = processedTransactions ) }
代码细节说明
- 状态封装:这里用了
Pair<MutableList<TransactionEntity>, BigDecimal>来同时跟踪「已处理的交易列表」和「当前余额」,如果你觉得可读性不够,也可以自定义一个数据类来封装状态:
替换掉private data class ProcessingState( val transactions: MutableList<TransactionEntity>, val currentBalance: BigDecimal )fold里的Pair,代码会更清晰。 - 日期排序:一定要确保交易按时间正序(从最早到最晚)排列,否则余额计算逻辑会完全错误,如果原始数据的顺序不确定,
sortedBy { it.date }这一步必不可少。 - 金额正负:如果你的
Transaction里的amount是用正数表示支出、负数表示收入,那需要把add改成subtract,或者提前对金额取反,根据你的业务规则调整即可。
简化版思路(只处理余额字段)
如果已经有了TransactionEntity列表,只想单独填充balanceBefore和balanceAfter,可以单独写一个函数:
fun List<TransactionEntity>.fillBalances(initialBalance: BigDecimal): List<TransactionEntity> { return fold(mutableListOf<TransactionEntity>() to initialBalance) { (list, balance), entity -> entity.balanceBefore = balance entity.balanceAfter = balance.add(entity.amount) list.apply { add(entity) } to entity.balanceAfter }.first }
内容的提问来源于stack exchange,提问作者noloman
相关产品推荐
相关产品推荐

