Expression Rule

Hi,

I have a below output from my expression

My requirement is if "expr" of every Dictionary contains "rowcode" that row code needs to be replaced by "expr" of that particular rowcode (for eg: "(FRML_88_1+FRML_88_2)" this expression contains rowcode so i need to replace it with expr "((123/12)+(1284*64))" and  the final output be like  "(((123/12)+(1284*64))*(9090+122))"

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer

    Can you clarify what you're trying to do here?  I've read this a few times now and I can't quite figure out what ```if "expr" of every Dictionary contains "rowcode"``` means.  From your screenshot it looks like every entry contains both "rowcode" and "expr" properties.

  • I digested this a little bit, and it appears that "expr" is either a mathematical expression or a reference to another expression based on the rowcode, so the rowcode should be replaced into that expression when it exists in the expr.

    Great case for a recursive function here.  This example assumes there are always 2 objects within the "expr" separated by +,-,* or /, and the rowcode references always contain the text "FRML".

    Additionally, to assist I've created a new local!data2 variable which breaks out the expr into 2 separate parts and operator, easier to parse that way.

    Primary, rule!chris_21640():

    a!localVariables(
      local!data: {
        a!map(expr: "(123/12)", rowcode: "FRML_88_1"),
        a!map(expr: "(1284*64)", rowcode: "FRML_88_2"),
        a!map(expr: "(FRML_88_1+FRML_88_2)", rowcode: "FRML_88_3"),
        a!map(expr: "(9090+122)", rowcode: "FRML_88_4"),
        a!map(expr: "(FRML_88_3*FRML_88_4)", rowcode: "FRML_88_5")
      },
      local!operators: {"+","-","*","/"},
      local!data2: a!flatten(
        a!forEach(
          items: local!data,
          expression: {
            a!localVariables(
              local!row: fv!item.expr,
              local!rowcode: fv!item.rowcode,
              reject(
                fn!isnull,
                a!flatten(
                  a!forEach(
                    items: local!operators,
                    expression: if(
                      search(fv!item,local!row)>0,
                      a!localVariables(
                        local!operator: fv!item,
                        local!items: split(stripwith(local!row,"()"),fv!item),
                        a!map(
                          expr1: local!items[1],
                          expr2: local!items[2],
                          operator: local!operator,
                          rowcode: local!rowcode
                        )
                      ),
                      null
                    )
                  )
                )
              )
            )
          }
        )
      ),
      
      a!forEach(
        items: local!data2,
        expression: rule!chris_21640_recur(
          data: local!data2,
          expr1: fv!item.expr1,
          expr2: fv!item.expr2,
          operator: fv!item.operator
        )
      )
    )

    And the helper recursive rule, rule!chris_21640_recur():

    concat(
      "(",
      if(
        search("FRML",ri!expr1)>0,
        a!localVariables(
          local!index: wherecontains(ri!expr1,ri!data.rowcode),
          rule!chris_21640_recur(
            data: ri!data,
            expr1: index(ri!data.expr1,local!index,null),
            expr2: index(ri!data.expr2,local!index,null),
            operator: index(ri!data.operator,local!index,null),
          )
        ),
        ri!expr1,
      ),
      ri!operator,
      if(
        search("FRML",ri!expr2)>0,
        a!localVariables(
          local!index: wherecontains(ri!expr2,ri!data.rowcode),
          rule!chris_21640_recur(
            data: ri!data,
            expr1: index(ri!data.expr1,local!index,null),
            expr2: index(ri!data.expr2,local!index,null),
            operator: index(ri!data.operator,local!index,null),
          )
        ),
        ri!expr2,
      ),
      ")"
    )

    This will return a list of mathematical expressions, replacing (recursively) rowcode references within the expressions. 

  • 0
    Appian Employee
    in reply to Chris

    This is a fun problem! I think you could simplify it by assuming that the operators don't need to be specified individually, since each of the sub-expressions are valid on their own. If you do, then you can do a more straightforward substitute(). Also, this is one of the few examples where the reduce() function actually makes this easier! The important thing here is that the result of the previous must be used for the next loop (since you'd need that to use the result of FRML_88_3 in the last item). Here's what I did:

    Main Rule

    a!localVariables(
      local!data: {
        a!map(
          expr: "(123/12)",
          rowcode: "FRML_88_1"
        ),
        a!map(
          expr: "(1284*864)",
          rowcode: "FRML_88_2"
        ),
        a!map(
          expr: "(FRML_88_1+FRML_88_2)",
          rowcode: "FRML_88_3"
        ),
        a!map(
          expr: "(9090+122)",
          rowcode: "FRML_88_4"
        ),
        a!map(
          expr: "(FRML_88_3*FRML_88_4)",
          rowcode: "FRML_88_5"
        )
      },
      reduce(
        rule!PDL_RecursiveSupportingRule,
        local!data,
        enumerate(length(local!data)) + 1,
      )
    )

    Supporting Rule

    a!forEach(
      items: ri!data,
      expression: if(
        search(
          index(ri!data.rowcode, ri!index, {}),
          fv!item.expr
        ) > 0,
        a!update(
          data: fv!item,
          index: "expr",
          value: substitute(
            fv!item.expr,
            index(ri!data.rowcode, ri!index, {}),
            index(ri!data.expr, ri!index, {}),     
          ),
        ),
        fv!item
      )
    )

  • Nice code, much cleaner!  Would love to runs some tests cases with it but alas, we are only on 21.1 (no a!update() yet)!

  • Thanks Chris for your response, it's working as expected

  • Thanks  for your reply, it's  really a clean code