onegative has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I am having difficulty in building a looping construct to take an initial element and perform a database lookup of its sub-elements which can contain sub-elements which results in the need to then perform additional lookups of one or more elements which again may contain more sub-elements which again may require an additional lookups of sub-elements until the sub-elements can no longer be sub-divided. Then all the while collecting the lowest common denominator of the elements called DEVICES and storing in a single array to be returned as a result.
Here is a look the best I can represent of what the data could look like. I am using psuedo-data to represent what I am trying to accomplish.
There are three types of data. Group, User, Device.
So the top level is a Group which can contain any of the data types described above.
GROUP1 contains GROUP2, DEVICE1, DEVICE2, DEVICE3 GROUP2 contains GROUP3, GROUP4, DEVICE4, DEVICE5, USER1 GROUP3 contains GROUP5, USER2, DEVICE6, DEVICE7 GROUP4 contains DEVICE8, DEVICE9, USER2 USER1 contains DEVICE10, DEVICE11, DEVICE12 GROUP5 contains DEVICE13, DEVICE14 USER2 conatins DEVICE15, DEVICE16, DEVICE17

And my results would be DEVICE1 ... DEVICE17

So the initial query is to GROUP1 which contains a sub-group and 3 devices. So I store the 3 devices and then I need to process GROUP2 which contains 2 sub-groups, 2 devices and a user. Then I store those 2 devices in the original array and then process GROUP3, GROUP4 and USER1 to extract their devices which I again store in the device array and so on until I can't break down any sub-elements further. The problem I am having is understand the logic construct that needs to be used to extract devices from the initial group and then sub-group and/or users embedded as members of the subsequent elements extracted. The sub-elements could contain many layers of sub-groups after sub-groups and this is where I am having trouble understanding how I would build the logic. I can code most of it but I am really having trouble grasping the deeper logic to continue to process sub-tree after sub-tree without writing the results to files and then reading them after I have exhuasted the sub-trees to the LCD.

If I just had an example to see I think the light would go on! But I keep hitting a deadend trying to build the logic in my mind.
Any and all suggestions would be greatly appreciated.
Thanks in advance for your help,
Danny

Replies are listed 'Best First'.
Re: Unknown levels of sub-element extraction
by kyle (Abbot) on Dec 06, 2008 at 04:22 UTC

    This looks like recursion to me.

    sub devices_for { my ( $thing ) = @_; my @subs = query( $thing ); return map { /^DEVICE\d+/ ? $_ : devices_for( $_ ) } @subs; }

    The first call, devices_for( 'GROUP1' ), causes a query( 'GROUP1' ). The map sends the device entries right through but causes a recursive call for 'GROUP2' and so forth. What the initial call for 'GROUP1' returns just a list of devices. Slip in a sort if you need them in order.

    Update: Slightly better:

    sub devices_for { my ( $thing ) = @_; return $thing if $thing =~ /^DEVICE\d/; return map { devices_for( $_ ) } query( $thing ); }

    Or all in "one step":

    sub devices_for { return ( $_[0] =~ /^DEVICE\d/ ) ? $_[0] : map { devices_for( $_ ) } query( $_[0] ); }