Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- JMP User Community
- :
- Blogs
- :
- Uncharted
- :
- Head Arg Recurse Formula

- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Email to a Friend
- Printer Friendly Page
- Report Inappropriate Content

Apr 3, 2015 7:11 AM
(1128 views)

Head Arg Recurse Formula

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.

Article Tags

You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.