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
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.
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 for your reply, it's really a clean code