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

Monks, I'm trying to visualize the best method to handle the following:

I have a sorted array with many elements, and for some reason, I need to pull out a slice from that list and insert a placeholder which points to the location of the sub-list. I must do the same many times, both to the original list and to the new ones. In other words, I must construct a tree from a list, inserting elements where a new branch appears. When the special tree is finished, I have to traverse it in order, doing some actions based on the type of the node (original leaves vs new ones).

Should I use one of the available modules to handle trees, linked lists or such, or I must keep this simple by blessing some structures? Hints?

Thank you!

Replies are listed 'Best First'.
Re: How might I handle a special tree?
by LanX (Saint) on Dec 07, 2014 at 22:19 UTC
    The target structure is an array of arrays, see perldsc

    You can use splice to extract regions out if the original array (i.e. if you don't want to copy to a new one)

    Otherwise just slice and copy.

     $new[$i++] =  [ @old[$start..$end ] ]

    edit

    And for traversing use a recursive function which calls itself when an array-ref is read.

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

      I thought about AoA, but that is not enought. For example:

      [1,2,3,4,5,6,7,8,9]

      should be converted to something like this:

      [1,[2,3,4],5,[6,[7,8,9]]]

      What is missing in this structure is the placeholder, which will have a group name... that's a new value in the list!

      I guess that I could manage the first element in each list as the name of the placeholder, resulting something like this:

      [A,1,[B,2,3,4],5,[C,6,[D,7,8,9]]]

      BTW, while traversing, how could I recognize if current element is a scalar or another list to recurse?

        > how could I recognize if current element is a scalar or another list to recurse?

        with ref

        > What is missing in this structure is theplaceholder, which will have a group name... 

        No idea what you may mean...

        update

        Maybe

         [ {A => [1, {B => [2,3,4]} ,5, {C => [ 6, { D => [7,8,9] } ] } ]

        ? ? ?

        (untested)

        update

        TIMTOWTDI

        Instead of a one element hash you could use a 2 element array.

        Or put the "placeholder" into the sub array as first element.

        I personally prefer the hash solution for readability, but keep in mind that keys are stringified.

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: How might I handle a special tree?
by BrowserUk (Patriarch) on Dec 07, 2014 at 22:59 UTC

    Using splice to replace a subset of the top level array with an anonymous array holding the values replaced is fairly easy:

    @sorted = 0 .. 9;; splice @sorted, 1, 8, [ @sorted[ 1 .. 8 ] ];; pp @sorted;; (0, [1, 2, 3, 4, 5, 6, 7, 8], 9)

    However, if you need to perform that same operation on one of the nested anonymous arrays, it gets somewhat more complicated:

    splice @{ $sorted[1] }, 1, 6, [ @{ $sorted[ 1] }[ 1 .. 6 ] ];; pp @sorted;; (0, [1, [2, 3, 4, 5, 6, 7], 8], 9)

    And if you need to go deeper still, it starts to get quite unweildy:

    splice @{ $sorted[1][1] }, 1, 4, [ @{ $sorted[1][1] }[ 1 .. 4 ] ];; pp @sorted;; (0, [1, [2, [3, 4, 5, 6], 7], 8], 9)

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: How might I handle a special tree?
by Anonymous Monk on Dec 08, 2014 at 13:16 UTC
    Each node in the tree should be unique, and each node has two attributes: whether or not it appears in "list #1" and whether or not in "list #2."
      That makes no sense as a solution to the OP's question.

      The nodes in the original list are unique, and actually are the keys of some hashes, and the order in the list is based on one of them. The new ones (branches) are labels that group some old nodes based on values from other hash, and it's name will not duplicate any existing key. Being the first element of any nested list is enougth to know the type of it.

      I think I'll start with about a thousand nodes in a list, and I don't know how "tall" the resulting tree will be. It'll depend on some tunning of the parameters.

Re: How might I handle a special tree?
by vitoco (Hermit) on Dec 08, 2014 at 22:01 UTC

    With the inserted placeholder in the first position of every array as a grouping item, the traverse subroutune looks like this:

    my @xx = ['A',1,['B',2,3,4],5,['C',6,['D',7,8,9]]]; traverse("", @xx); sub traverse { my $d = $_[0] . "/" . $_[1][0]; for my $i (1 .. @{$_[1]}-1) { if (ref $_[1][$i] eq 'ARRAY') { traverse($d, $_[1][$i]); } else { print $d . "/" . $_[1][$i] . "\n"; } } }

    The result is:

    /A/1 /A/B/2 /A/B/3 /A/B/4 /A/5 /A/C/6 /A/C/D/7 /A/C/D/8 /A/C/D/9

    I tried to manage the route of groups and subgroups with another array, but got this message when trying to add the first items from the second array to the first one:

    Can't use string ("A") as an ARRAY ref while "strict refs" in use at t +est.pl line 6

    I couldnīt get rid of it. I also tried passing the arguments by reference, but I got many other error mesages on every change I did.

      your mom is a special tree