inspired by Is there a way to extract columns used in a formula? and Ian@JMPcomment.
dt = New Table( "Get Columns in Formula",
Add Rows( 20 ),
New Column( "H", Numeric, "Continuous", Format( "Best", 12 ), Formula( Random Uniform() ) ),
New Column( "W", Numeric, "Continuous", Format( "Best", 12 ), Formula( Random Uniform() ) ),
New Column( "D", Numeric, "Continuous", Format( "Best", 12 ), Formula( Random Uniform() ) ),
New Column( "V", Numeric, "Continuous", Format( "Best", 12 ), Formula( (:W * :H * :D) / 10 ) )
);
formula = dt:V << getformula();
// function to find leaves in formula that are columns in the table
findColumns = Function( {frm, cols},
{h = Head( frm ), n = N Arg( frm ), i, result = {}}, // local variables
If( n == 0, // head node has no children, it is a leaf
If( Contains( cols, Name Expr( h ) ), // is the leaf in the list of columns?
Insert Into( result, Name Expr( h ) ); // yes -> add to result
)
,
For( i = 1, i <= n, i++, // not a leaf, get children's results
Insert Into( result, Recurse( Arg( frm, i ), cols ) )
)
);
result// return the result
);
answer = findColumns( Name Expr( formula ), dt << GetColumnNames );
Show( formula, answer );
formula = (:W * :H * :D) / 10;
answer = {:W, :H, :D};
The findColumns function defined on lines 10-22 takes two arguments, frm, the formula to examine, and cols, a list of valid column names to extract. The Head of the example expression is Divide(...) which has two children (the answer from N Arg). The if statement sees there are children and uses the recurse function to process each child. The multiply child has three children. the :W child has no children, and the list of columns from the data table contains :W, so :W is inserted into a list and the list returned, where that list is inserted into a list. The multiply child then sends the 2nd arg to recurse and :H is appended. Eventually the 10 (the 2nd child of Divide) is sent to recurse, but isn't in the list of columns, so does not appear in the answer.
Recursion takes some effort every time. But it makes a simple-looking program.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.