EasyCFM.COM ColdFusion Forums / Tutorial Requests! / Recursion?

   Reply to Discussion | New Discussion << previous || next >> 
Posted By Discussion Topic: Recursion? -- page: 1 2

book mark this topic Printer-friendly Version  send this discussion to a friend  new posts last

louissto56
02-06-2008 @ 6:04 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Moderator
Posts: 1149
Joined: Jan 2007

Hey guys. This isn't a request but more of a question.

I am thinking about making a tutorial based on the basics of recursion. There is a GREAT tutorial about recursion by matt (http://tutorial478.easycfm.com/)
but it assumes the user is fairly advanced. I was going to make it on basic recursion without using a DB.

Was thinking along the lines of making a function that finds a factorial of a number using recursion and much much more!

Whadayathink!
Louis

____________________________
My Biz List.com.au :: Feb 08

gmilby
02-06-2008 @ 7:23 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Senior Member
Posts: 281
Joined: Nov 2007

as pathetic as this is, i'll ask anyway...
what are some practical applications for this?
my exposure to recursion is next to nuttin'


Success is the ablity to go from one failure to another with no loss of enthusiasm.
-Sir Winston Churchill

gmilby
02-06-2008 @ 7:32 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Senior Member
Posts: 281
Joined: Nov 2007

oh btw - make the tutorial... "easy" is always good. maybe they should make a site about easy cfm code?
Playful

Success is the ablity to go from one failure to another with no loss of enthusiasm.
-Sir Winston Churchill

megan
02-06-2008 @ 7:43 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Moderator
Posts: 2398
Joined: Jan 2003

Hi Greg - an example of how I use recursion is in dynamically creating a site map for an app of mine.  the app allows the user to have unlimited pages, sub pages sub sub pages ad infinitum... and I use recursion to create the site map for it, but it would be could on a directory site, for getting and displaying links to categories & sub categories, or a set of help docs getting topics and sub topics ... hth ~megan

We have art so that we shall not die of reality ~ Nietzsche

louissto56
02-06-2008 @ 7:44 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Moderator
Posts: 1149
Joined: Jan 2007

Well if you look at matts tutorial, you can use it for multi depth categories.

You really have to use your imagination for this one. Basically it is a function that calls itself. So it is similar to doing a loop.

Louis

____________________________
My Biz List.com.au :: Feb 08

dduck1934
02-06-2008 @ 2:35 PM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Senior Member
Posts: 264
Joined: Sep 2004

I encouraged Matt to post his tutorial on recursion because i was using recursion a good bit in some of my applications.

Recently what ive used recursion for is looping through xml, or going through a database with a parent/child relationship (like you said.. similar to a category system).

I think it would be a nice tutorial to have a beginners tutorial on recursion.  It can be with factorials, but Id recommend some more "real world" examples.

Cheers,
-Matthew (dduck)

gmilby
02-06-2008 @ 7:55 PM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Senior Member
Posts: 281
Joined: Nov 2007

thanks for the examples of use Smile

once louis does this tut i'll go through it - then the advanced one. maybe i can find a 'new' use for it(?)

Success is the ablity to go from one failure to another with no loss of enthusiasm.
-Sir Winston Churchill

louissto56
02-07-2008 @ 12:33 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Moderator
Posts: 1149
Joined: Jan 2007

Yeah I want to include real life examples. Has anyone got any ideas on what I could do for that. I don't really want to use a database cuz it just complicates things for the reader.

Looping through XML is a good one. Any others?

Louis

____________________________
My Biz List.com.au :: Feb 08

eliasjp
04-09-2009 @ 9:14 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
New Member
Posts: 2
Joined: Apr 2009

HI Guys,

Im having dificulties downloading the source code for this tutorial. Do you know I could get it?

Please let me know this is exactly what Im needing for an app.

Thanks

This message was edited by eliasjp on 4-9-09 @ 9:15 AM

megan
04-09-2009 @ 9:32 AM
Reply
Edit
Profile
Send P.M.
My Gravatar!
Powered by Gravatar
Moderator
Posts: 2398
Joined: Jan 2003

Hi - I can't do anything about the missing "listing" files associated with the tutorial but below is the code for the cfc and the demo (index.cfm) which were in the download

cfc:

<!---
filename:          recursive/com/recursiveObject.cfc
date created:     8/17/06
author:               Rachel Queen Services Group, LLC (cf-content@rachelqueensg.com)
purpose:          a recursive object
                         
     // this document and its contents are protected by U.S. and International copyright laws
     // Copyright 2005-2006, Rachel Queen Services Group, LLC All Rights Reserved
--->

<cfcomponent hint="An object for recursive searching" displayname="objRecursive" output="false">
     
     <!--- "constructors" --->
     <cfscript>
          variables.properties = structNew();
     </cfscript>
     
     <!--- BEGIN init() method --->
     <cffunction name="init" hint="Initializes the object" returntype="recursiveObject" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="qry" hint="The query object that the recursion is based upon" required="yes" type="query" />
          <cfargument name="dspField" hint="The name of the field in the provided query from which to retrieve the display text" required="yes" type="string" />
          <cfargument name="parentField" hint="The name of the field in the provided query that contains the parent ID; this is typically the PRIMARY KEY for the table" required="yes" type="string" />
          <cfargument name="childOfField" hint="The name of the field in the provided query that contains the ID of the parent element; this is often named 'parent_id'" required="yes" type="string" />
          
          <cfscript>
               setProperty("qry", arguments.qry);
               setProperty("dspField", arguments.dspField);
               setProperty("parentField", arguments.parentField);
               setProperty("childOfField", arguments.childOfField);
               return this;
          </cfscript>
     </cffunction>
     <!--- END init() method --->
     
     <!--- BEGIN getProperty() method --->
     <cffunction name="getProperty" hint="Returns the value of the provided property" returntype="any" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="propertyName" hint="Name of the property whose value to get" type="string" required="yes" />
          
          <cfscript>
               if (structKeyExists(variables.properties, arguments.propertyName)) {
                    return variables.properties[arguments.propertyName];
               } else {
                    return "The requested property (" & arguments.propertyName & ")does not exist";
               }
          </cfscript>
     </cffunction>
     <!--- END getProperty() method --->
     
     <!--- BEGIN setProperty() method --->
     <cffunction name="setProperty" hint="Sets the value of the provided property" returntype="void" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="propertyName" hint="Name of the property whose value to get" type="string" required="yes" />
          <cfargument name="propertyValue" hint="Provides the value of the property" type="any" required="yes" />
          
          <cfset variables.properties[arguments.propertyName] = arguments.propertyValue />
     </cffunction>
     <!--- END setProperty() method --->
     
     <!--- BEGIN getRecursiveList() method --->
     <cffunction name="getRecursiveList" hint="Returns an xhtml list from a recursive query search" returntype="string" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="parentID" hint="Provides the ID of the parent category to search in; if searching from the root level, pass in zero (0) to this argument" required="yes" type="numeric" />
          <cfargument name="listType" hint="The type of list; either unordered (<ul>) or ordered (<ol>); defaults to unordered" required="no" type="string" default="ul" />
          
          <cfscript>
               var strOut = "";
               var qSubs = "";
               var i = 1;
               qSubs = getSubs(arguments.parentID);
               if (qSubs.recordCount GT 0) {
                    for (; i LTE qSubs.recordCount; i=i+1) {
                         strOut = strOut & "<li>" & qSubs[getProperty('dspField')];
                         strOut = strOut & getRecursiveList(qSubs[getProperty('parentField')], arguments.listType);
                         strOut = strOut & "</li>";
                    }
                    strOut = "<" & listType & ">" & strOut & "</" & listType & ">";
               }
               return strOut;
          </cfscript>
     </cffunction>
     <!--- END getRecursiveList() method --->
     
     <!--- BEGIN getRecursiveOptions() method --->
     <cffunction name="getRecursiveOptions" hint="Returns a string containing the option tags for an option list from a recursive query search" returntype="string" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="parentID" hint="Provides the ID of the parent category to search in" required="yes" type="string" />
          
          <cfscript>
               var strOut = "";
               var qSubs = "";
               var option = "<option value=""[id]"">[dsp]</option>";
               var dsp = "";
               var i = 1;
               var depth = 0;
               qSubs = getSubs(arguments.parentID);
               if (qSubs.recordCount GT 0) {
                    for (i=1; i LTE qSubs.recordCount; i=i+1) {
                         depth = getDepth(qSubs[getProperty('parentField')]);
                         strOut = strOut & option;
                         strOut = replace(strOut, "[id]", qSubs[getProperty('parentField')]);
                         dsp = repeatString(" – ", depth-1) & qSubs[getProperty('dspField')];
                         strOut = replace(strOut, "[dsp]", dsp);
                         strOut = strOut & getRecursiveOptions(qSubs[getProperty('parentField')]);
                    }
               }
               return strOut;
          </cfscript>
     </cffunction>
     <!--- END getRecursiveOptions() method --->
     
     <!--- BEGIN getBreadcrumbs() method --->
     <cffunction name="getBreadcrumbs" hint="Returns a string containing the breadcrumb trail to the input child" returntype="string" output="true" access="public">
          <!--- set the method arguments --->
          <cfargument name="childID" hint="The ID of the child whose parent is being searched for" required="yes" type="string" />
          <cfargument name="pageName" hint="The name of the page (template/script) to be used in building the links; defaults to 'index.cfm'" required="no" type="string" default="index.cfm" />
          
          <cfscript>
               var strOut = "";
               var qParent = "";
               var link = "";
               link = "<a href=""" & arguments.pageName & "?id=[parentField]"">[dspField]</a>";
               if (NOT structKeyExists(variables, "childID")) {
                    variables.childID = arguments.childID;
               }
               qParent = getParent(arguments.childID);
               if (qParent[getProperty('parentField')][1] NEQ variables.childID) {
                    link = replace(link, "[parentField]", qParent[getProperty('parentField')][1]);
                    link = replace(link, "[dspField]", qParent[getProperty('dspField')][1]);
               } else {
                    link = qParent[getProperty('dspField')][1];
               }
               if (isNumeric(qParent[getProperty('childOfField')][1]) AND qParent[getProperty('childOfField')][1] NEQ 0) {
                    strOut = getBreadcrumbs(qParent[getProperty('childOfField')][1], arguments.pageName) & " > " & link & strOut;
               } else {
                    strOut = link & strOut;
               }
               return strOut;
          </cfscript>
     </cffunction>
     <!--- END getBreadcrumbs() method --->
     
     <!--- BEGIN getDepth() method --->
     <cffunction name="getDepth" hint="Returns the numeric value of how many levels deep an element resides in a recursive query (NOTE: a return value of 1 indicates a top-level element, so depending on your purpose, you might need to subtract 1 from the result)" returntype="numeric" output="false" access="public">
          <!--- set the method arguments --->
          <cfargument name="childID" hint="Provides the ID of the child whose parent is being searched for" required="yes" type="string" />
          
          <cfscript>
               var depth = 1;
               var qParent = "";
               qParent = getParent(arguments.childID);
               if (qParent[getProperty('childOfField')][1] GT 0) {
                    depth = depth + getDepth(qParent[getProperty('childOfField')][1]);
               }
               return depth;
          </cfscript>
     </cffunction>
     <!--- END getDepth() method --->
     
     <!--- BEGIN getSubs() method --->
     <cffunction name="getSubs" hint="Performs a QofQ in order to check for sub-categories; returns a query object; used internally" returntype="query" output="false" access="private">
          <!--- set the method arguments --->
          <cfargument name="parentID" hint="Provides the ID of the parent category to search in; if searching from the root level, pass in zero (0) to this argument" required="yes" type="numeric" />
          
          <cfscript>
               var qOut = "";
               var qIn = getProperty('qry');
          </cfscript>
          
          <cfquery name="qOut" dbtype="query">
          SELECT * FROM qIn
               WHERE #getProperty('childOfField')# = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.parentID#" />;
          </cfquery>
          
          <cfreturn qOut />
     </cffunction>
     <!--- END getSubs() method --->
     
     <!--- BEGIN getParent() method --->
     <cffunction name="getParent" hint="Performs a QofQ to find a child's parent; returns a query object; used internally" returntype="query" output="false" access="private">
          <!--- set the method arguments --->
          <cfargument name="childID" hint="The ID of the child whose parent to find" required="yes" type="numeric" />
          
          <cfscript>
               var qOut = "";
               var qIn = getProperty('qry');
          </cfscript>
          
          <cfquery name="qOut" dbtype="query" maxrows="1">
          SELECT * FROM qIn
               WHERE #getProperty('parentField')# = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.childID#" />;
          </cfquery>
          
          <cfreturn qOut />
     </cffunction>
     <!--- END getParent() method --->
     
</cfcomponent>

end cfc

index.cfm (demo)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<cfsilent>
<!---
filename:          recursive/tut/index.cfm
date created:     8/16/06
author:               Rachel Queen Services Group, LLC (cf-content@rachelqueensg.com)
purpose:          recursiveObject demo page
                         
     // this document and its contents are protected by U.S. and International copyright laws
     // Copyright 2005-2006, Rachel Queen Services Group, LLC All Rights Reserved
--->

<cfset variables.dsn = "myDSN" />

<cfquery name="variables.qCats" datasource="#variables.dsn#">
SELECT categoriesID, category_name, parent_id
     FROM tblCategories
ORDER BY parent_id, category_name;
</cfquery>

</cfsilent>
<cfscript>
     variables.cfcPath = "path.from.wwwroot.to.recursiveObject";
     variables.objRecursion = createObject("component", variables.cfcPath).init(variables.qCats, "category_name", "categoriesID", "parent_id");
</cfscript>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <style type="text/css">
     html, body {
          margin: 0 auto;
          text-align: center;
          width: 760px;
          font-size: 100.1%;
     }
     div#wrapper {
          width: inherit;
          text-align: left;
     }
     div#breadcrumbs {
          font-size: 75%;
     }
     table.cfdump_query {
          font-size: xx-small;
          font-family: verdana, arial, helvetica, sans-serif;
          cell-spacing: 2px;
          background-color: #884488 ;
     }
     table.cfdump_query th {
          text-align: left;
          color: white;
          padding: 5px;
     }
     table.cfdump_query td {
          padding: 3px;
          background-color: #ffffff;
          vertical-align : top;
     }
     table.cfdump_query th.query {
          background-color: #a6a ;
     }
     table.cfdump_query td.query {
          background-color: #fdf ;
     }
     </style>
     <title>A Recursive Demo</title>
</head>

<body>

<cfoutput>
<div id="wrapper">
     <h1>A Recursive Demo</h1>

     <div>
          <h3>The Query</h3>
          <table class="cfdump_query">
               <tr>
                    <th class="query" colspan="4">This is the ONLY database query!</th>
               </tr>
               <tr>
                    <td class="query"> </td>
                    <td class="query">CATEGORIESID</td>
                    <td class="query">CATEGORY_NAME</td>
                    <td class="query">PARENT_ID</td>
               </tr>
               <tr>
                    <td class="query">1</td>
                    <td valign="top">8</td>
                    <td valign="top">Another Top-Level Cat</td>
                    <td valign="top">0</td>
               </tr>
               <tr>
                    <td class="query">2</td>
                    <td valign="top">1</td>
                    <td valign="top">General Information</td>
                    <td valign="top">0</td>
               </tr>
               <tr>
                    <td class="query">3</td>
                    <td valign="top">2</td>
                    <td valign="top">Membership Information</td>
                    <td valign="top">0</td>
               </tr>
               <tr>
                    <td class="query">4</td>
                    <td valign="top">9</td>
                    <td valign="top">Yet Another Top-Level Cat</td>
                    <td valign="top">0</td>
               </tr>
               <tr>
                    <td class="query">5</td>
                    <td valign="top">3</td>
                    <td valign="top">Billing Information</td>
                    <td valign="top">2</td>
               </tr>
               <tr>
                    <td class="query">6</td>
                    <td valign="top">4</td>
                    <td valign="top">Rules of Conduct</td>
                    <td valign="top">2</td>
               </tr>
               <tr>
                    <td class="query">7</td>
                    <td valign="top">5</td>
                    <td valign="top">Rules of Conduct II</td>
                    <td valign="top">4</td>
               </tr>
               <tr>
                    <td class="query">8</td>
                    <td valign="top">6</td>
                    <td valign="top">Rules of Conduct III</td>
                    <td valign="top">5</td>
               </tr>
               <tr>
                    <td class="query">9</td>
                    <td valign="top">7</td>
                    <td valign="top">Rules of Conduct IV</td>
                    <td valign="top">6</td>
               </tr>
          </table>
     </div>

     <div id="breadcrumbs">
          <h3>Breadcrumbs</h3>
          #variables.objRecursion.getBreadcrumbs(7, "index.cfm")#
     </div>
     
     <div>
          <h3>A SelectBox Form</h3>
          <form action="#cgi.script_name#" method="post">
               <div>
                    <div>
                         <label for="category_name">Category Name</label>
                         <input type="text" name="category_name" id="category_name" />
                    </div>
                    <div>
                         <label for="mySelect">Parent Category (optional):</label>
                         <select name="mySelect" id="mySelect">
                              #variables.objRecursion.getRecursiveOptions(0)#
                         </select>
                    </div>
                    <input type="submit" id="submit" value="Create It!" />
               </div>
          </form>
     </div>
     <div class="list">
          <h3>An Ordered List</h3>
          #variables.objRecursion.getRecursiveList(0, "ol")#
     </div>
     <div class="list">
          <h3>An Unordered List</h3>
          #variables.objRecursion.getRecursiveList(0, "ul")#
     </div>
</div>
</cfoutput>

</body>
</html>




-------------------------------------------------------
If you have a hobby you love, then you can create a profitable online business
that gives you an autopilot income stream in 30 days or less

PAGE: 1 2

Website Designed and Developed by Pablo Varando.