CodeIgniter Forums
Coding Geniuses: Answer this Question Please (best answer gets $20) - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forumdisplay.php?fid=23)
+--- Thread: Coding Geniuses: Answer this Question Please (best answer gets $20) (/showthread.php?tid=6992)

Pages: 1 2


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]danoph[/eluser]
I have an array of website pages that I want to sort. Right now, it is a one-dimensional array that I need to sort into a multi-dimensional array. Pages that have a "parent_thread" will need to fall under their appropriate parent thread in the array. A page can have an unlimited number of children pages. Here is the flat array:

Code:
Array
(
    [1] => stdClass Object
        (
            [id] => 1
            [parent_thread] =>
            [title] => Moneypete
            [permalink] => home
        )

    [2] => stdClass Object
        (
            [id] => 2
            [parent_thread] => 1
            [title] => Entrepreneurship
            [permalink] => entrepreneurship
        )

    [3] => stdClass Object
        (
            [id] => 3
            [parent_thread] => 2
            [title] => Ideas, Business Advices, and Franchises
            [permalink] => ideas_business_advice_franchises
        )

    [4] => stdClass Object
        (
            [id] => 4
            [parent_thread] => 2
            [title] => Practical help for Entrepreneur Startups
            [permalink] => practical-help-for-entrepreneur-startups
        )

    [5] => stdClass Object
        (
            [id] => 5
            [parent_thread] => 2
            [title] => Management & Leadership
            [permalink] => management_leadership
        )

    [6] => stdClass Object
        (
            [id] => 6
            [parent_thread] => 1
            [title] => Real Estate
            [permalink] => real_estate
        )

    [7] => stdClass Object
        (
            [id] => 7
            [parent_thread] => 1
            [title] => Stocks & Bonds
            [permalink] => stocks_bonds
        )

    [8] => stdClass Object
        (
            [id] => 8
            [parent_thread] => 1
            [title] => Financial Education
            [permalink] => financial_education
        )

    [9] => stdClass Object
        (
            [id] => 9
            [parent_thread] => 1
            [title] => Residential
            [permalink] => residential
        )

    [12] => stdClass Object
        (
            [id] => 12
            [parent_thread] => 1
            [title] => Commercial
            [permalink] => commercial
        )

    [15] => stdClass Object
        (
            [id] => 15
            [parent_thread] => 1
            [title] => E-Commerce
            [permalink] => ecommerce
        )

    [16] => stdClass Object
        (
            [id] => 16
            [parent_thread] => 15
            [title] => Videos
            [permalink] => videos
        )

}

I need to turn that array into :

Code:
Array
(
    [home] => stdClass Object
        (
            [id] => 1
            [parent_thread] =>
            [title] => Moneypete
            [permalink] => home
            [children] => Array
                (
                    [entrepreneurship] => stdClass Object
                        (
                            [id] => 2
                            [parent_thread] => 1
                            [title] => Entrepreneurship
                            [permalink] => entrepreneurship
                            [children] => Array
                                (
                                  [ideas_business_advice_franchises] => stdClass Object
                                    (
                                         [id] => 3
                                         [parent_thread] => 2
                                         [title] => Ideas, Business Advices, and Franchises
                                         [permalink] => ideas_business_advice_franchises
                                     )
                                )
                    [ecommerce] => stdClass Object
                        (
                            [id] => 15
                            [parent_thread] => 1
                            [title] => E-Commerce
                            [permalink] => ecommerce
                        )
                )


etc...

I need one sorting function to take the array and sort them into a structured site map in the format above.

Deadline: Thursday, March 20, 3pm CST.

It's been a while since I've had to tackle these kinds of algorithms, so the best answer will get 20 credits ($20) to http://graphicleftovers.com to buy logos and graphics and stuff. Thanks!


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]dtrenz[/eluser]
I couldn't resist...

As I was doing this I realized that the "id" property is redundant if you have a numeric array whose keys match the ids. So I did it with, and without ids.

DISCLAIMER: I'm sure there are many better and more clever ways, but in an hour, this is what I came up with (including an infinite recursion by reference headache).

First, here it is to spec (with ids):

Code:
class Page
{
    public $id;
    public $parent_thread;
    public $title;
    public $permalink;
    public $children;
    
    public function __construct($id = 0, $parent_thread = NULL, $title = '', $permalink = '', $children = array())
    {
        $this->id = $id;
        $this->parent_thread = $parent_thread;
        $this->title = $title;
        $this->permalink = $permalink;
        $this->children = $children;
    }
}

$page_array = array(
    1 => new Page(1, NULL, 'Moneypete', 'home'),
    2 => new Page(2, 1, 'Entrepreneurship','entrepreneurship'),
    3 => new Page(3, 2, 'Ideas, Business Advices, and Franchises','ideas_business_advice_franchises'),
    4 => new Page(4, 2, 'Practical help for Entrepreneur Startups','practical-help-for-entrepreneur-startups'),
    5 => new Page(5, 2, 'Management & Leadership','management_leadership'),
    6 => new Page(6, 1, 'Real Estate','real_estate'),
    7 => new Page(7, 1, 'Stocks & Bonds','stocks_bonds'),
    8 => new Page(8, 1, 'Financial Education','financial_education'),
    9 => new Page(9, 1, 'Residential','residential'),
    12 => new Page(12, 1, 'Commercial','commercial'),
    15 => new Page(15, 1, 'E-Commerce','ecommerce'),
    16 => new Page(16, 15, 'Videos','videos')
);

print_r($page_array);

foreach ($page_array as $page)
{    
    if (!isset($page->parent_thread))
    {
        $new_page_array = array($page->permalink => $page);
    }
    else
    {
        $parent_thread = $page->parent_thread;
        
        $level_map = array($parent_thread);
        
        while (isset($page_array[$parent_thread]->parent_thread))
        {
            $parent_thread = $page_array[$parent_thread]->parent_thread;        
            $level_map[] = $parent_thread;    
        }
        
        $level_map = array_reverse($level_map);    
                
        $parent_array =& $new_page_array[$page_array[array_shift($level_map)]->permalink];        
        
        if (!empty($level_map))
        {
            foreach ($level_map as $level)
            {
                $parent_array =& $parent_array->children[$page_array[$level]->permalink];    
            }
        }
        
        $parent_array->children[$page->permalink] = $page;    
    }
}

print_r($new_page_array);


...and here it is w/o ids:

Code:
class Page
{
    public $parent_thread;
    public $title;
    public $permalink;
    public $children;
    
    public function __construct($parent_thread = NULL, $title = '', $permalink = '', $children = array())
    {
        $this->parent_thread = $parent_thread;
        $this->title = $title;
        $this->permalink = $permalink;
        $this->children = $children;
    }
}

$page_array = array(
    1 => new Page(NULL, 'Moneypete', 'home'),
    2 => new Page(1, 'Entrepreneurship','entrepreneurship'),
    3 => new Page(2, 'Ideas, Business Advices, and Franchises','ideas_business_advice_franchises'),
    4 => new Page(2, 'Practical help for Entrepreneur Startups','practical-help-for-entrepreneur-startups'),
    5 => new Page(2, 'Management & Leadership','management_leadership'),
    6 => new Page(1, 'Real Estate','real_estate'),
    7 => new Page(1, 'Stocks & Bonds','stocks_bonds'),
    8 => new Page(1, 'Financial Education','financial_education'),
    9 => new Page(1, 'Residential','residential'),
    12 => new Page(1, 'Commercial','commercial'),
    15 => new Page(1, 'E-Commerce','ecommerce'),
    16 => new Page(15, 'Videos','videos')
);

print_r($page_array);

foreach ($page_array as $page)
{    
    if (!isset($page->parent_thread))
    {
        $new_page_array = array($page->permalink => $page);
    }
    else
    {
        $parent_thread = $page->parent_thread;
        
        $level_map = array($parent_thread);
        
        while (isset($page_array[$parent_thread]->parent_thread))
        {
            $parent_thread = $page_array[$parent_thread]->parent_thread;        
            $level_map[] = $parent_thread;    
        }
        
        $level_map = array_reverse($level_map);    
                
        $parent_array =& $new_page_array[$page_array[array_shift($level_map)]->permalink];        
        
        if (!empty($level_map))
        {
            foreach ($level_map as $level)
            {
                $parent_array =& $parent_array->children[$page_array[$level]->permalink];    
            }
        }
        
        $parent_array->children[$page->permalink] = $page;    
    }
}

print_r($new_page_array);

it's all done in the main foreach loop. you can toss it in a function easy enough.

don't worry about the $20 credit...

hope this works for you.


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]danoph[/eluser]
Wow, I'm impressed. Worked perfectly!

You are good. Thanks for your help!

If you ever want the credits, just e-mail me info [at] bizwidgets.biz

Thanks again Smile


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]Derek Allard[/eluser]
SEE! Now THIS is why the CI community kicks ass. Super technical post asking for help, and within hours a super complex solution is presented, and as evidenced by dtrenz's asking for no money, it was obvious he did it just to help out a fellow CI-er, and/or for challenge.

dtrenz, my hats off, this just made my day - on behalf of all of CI, thanks Wink


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]Pygon[/eluser]
For fun (and not for money), I think I'll take a stab at this tomorrow.


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-19-2008

[eluser]danoph[/eluser]
Thanks for the help everyone. In case this may help someone, I figured out the easy part! I came up with a simple function to recursively iterate through the new pages array generated by dtrenz' function and print out the pages in a structured format:

Code:
function print_sitemap($pages, $level=0) {
    $return = '';
        
    foreach ($pages as $id => $page) {
        $return .= str_repeat(' ', 4*$level);
        $return .= '- '.$page->title.'<br />';
        if (!empty($page->children)) $return .= $this->print_sitemap($page->children, ($level+1));
    }
        
    return $return;
}

This generates:

Code:
Moneypete
    - Entrepreneurship
        - Ideas, Business Advices, and Franchises
        - Practical help for Entrepreneur Startups
        - Management & Leadership
    - Real Estate
    - Stocks & Bonds
    - Financial Education
    - Residential
    - Commercial
    - E-Commerce
        - Videos



Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-20-2008

[eluser]dtrenz[/eluser]
Glad I could help. Smile

Anyone interested in giving me a little instant karma by helping me with my CI problem?

edit: fixed, thanks derek j & xwero


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-20-2008

[eluser]danoph[/eluser]
Seems like you solved the problem before I could even take a look!

@dtrenz: I am using your code in my CI CMS system. It includes an interactive site map, that you built.

@everyone: The CMS is going to have some object relational stuff like RoR does. More objected oriented! I'm going to release it very soon, I hope.

Thanks!


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-20-2008

[eluser]Frank Rocco[/eluser]
dtrenz - very nice job.
I looked at it until my head hurt.<g>

Frank


Coding Geniuses: Answer this Question Please (best answer gets $20) - El Forum - 03-20-2008

[eluser]dtrenz[/eluser]
Heh, my head hurt quite a bit. I think I even went cross-eyed a few times. It's hard to step-through code like that in your head. I wish there was a PHP debugger with breakpoints and watch windows...