You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中如何将含复杂表达式的公式替换为实际值并展示?

替换Excel式公式中的变量为实际值以展示计算过程

问题场景

我开发的应用将类Excel风格的公式存储在数据库中,通过eval方法计算最终结果(比如公式"a + b - c"能正常执行得到结果)。现在需要实现一个功能:把公式中的变量、复杂表达式替换为实际取值后展示,让用户清晰看到计算过程。

比如当a=3、b=2、c=1时,将原公式"a + b - c"展示为"3 + 2 - 1"。

涉及的典型公式示例包括:

  • capital_commitment.committed_amount_cents * ( fund_unit_setting.management_fee * ( ( @end_date - @start_date ).to_i + 1 ) / 365 ) / 100
  • AccountEntry.total_amount(capital_commitment.account_entries, name: 'Cost Of Exited Investments', end_date: @end_date)
  • ( capital_commitment.unit_type && capital_commitment.unit_type == 'Series C' ) ? 0 : ( ( @current_portfolio_fmv + @distributions - @remittances ) * 0.2 )

解决方案代码

通过Ruby的parser库解析公式的AST(抽象语法树),提取所有需要求值的表达式,计算后生成映射表,后续即可用该映射表替换原公式中的表达式为实际值。

def parse_statement(binding)
  statement = formula
  buffer = Parser::Source::Buffer.new('(string)')
  buffer.source = statement
  ast = Parser::CurrentRuby.new.parse(buffer)

  expressions = []
  find_expressions(ast, expressions)
  expression_map = {}
  expressions.each do |exp|
    val = eval(exp, binding)
    expression_map[exp] = val unless (val.is_a?(ApplicationRecord) || val.is_a?(OpenStruct))
  end
  expression_map
end

def find_expressions(node, expressions)
  case node.type
  when :send
    expressions << node.loc.expression.source
  when :lvar, :ivar, :const
    expressions << node.loc.name.source
  when :str
    expressions << node.loc.expression.source
  end

  node.children.each do |child|
    find_expressions(child, expressions) if child.is_a?(Parser::AST::Node)
  end
end

代码说明

  1. AST解析:使用Parser::CurrentRuby将公式字符串解析为抽象语法树,精准识别公式中的变量、方法调用、字符串等表达式。
  2. 表达式提取:递归遍历AST节点,收集所有需要求值的表达式(包括实例变量、局部变量、常量、方法调用、字符串)。
  3. 求值与映射:通过eval结合当前上下文的binding计算每个表达式的实际值,生成表达式到值的映射表(排除ActiveRecord模型和OpenStruct实例,避免展示无意义的对象引用)。
  4. 替换展示:基于生成的expression_map,即可将原公式中的对应表达式替换为实际值,得到用户可读的计算过程展示。

内容的提问来源于stack exchange,提问作者Mohith Thimmaiah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:18:13