HELP - advanced array merge

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
seigan
Forum Newbie
Posts: 7
Joined: Sat Sep 27, 2008 7:23 am

HELP - advanced array merge

Post by seigan »

Hi all,
I'm currently working on a projekt that demands multidimensions array that are quite "deep". Now I need to merge many of theese in to one big multi dimesion array that hold the whole structure and data. And it is a litle tricky for me...

For example do I have:
$multi['users_collection'][0]['user'][0]['id'] = id;
$multi['users_collection'][0]['user'][0]['name'] = name;
$multi['users_collection'][0]['books'][0]['book'][0]['id'] = id;
$multi['users_collection'][0]['books'][0]['book'][0]['name'] = name;


So far so good... I works no problem. But now I want to add a bok to the collection of book but with the same user as folow.The array looks like this:

$mult2i['users_collection'][0]['books'][0]['book'][0]['id'] = id;
$multi2['users_collection'][0]['books'][0]['book'][0]['name'] = name;

And I whant it to become:

$multi['users_collection'][0]['user'][0]['id'] = id;
$multi['users_collection'][0]['user'][0]['name'] = name;
$multi['users_collection'][0]['books'][0]['book'][0]['id'] = id;
$multi['users_collection'][0]['books'][0]['book'][0]['name'] = name;
$multi['users_collection'][0]['books'][1]['book'][0]['id'] = id; *
$multi['users_collection'][0]['books'][1]['book'][0]['name'] = name; *

*(note the number 1 after 'book').

As you see these two arrays is in two completly diffrent arrays I might add. I can't use:

$new_book['book'][0]['id'] = id;
array_push($multi['users_collection'][0]['books'], $new_book)

I have to merge the whole structure and make it react as I want it to react.


It becomes even more fun when I whant to add a whole new user collection as folows:

$multi3['users_collection'][1]['user'][0]['id'] = id;
$multi3['users_collection'][1]['user'][0]['name'] = name;
$multi3['users_collection'][1]['books'][0]['book'][0]['id'] = id;
$multi3['users_collection'][1]['books'][0]['book'][0]['name'] = name;
$multi3['users_collection'][1]['books'][1]['book'][0]['id'] = id;
$multi3['users_collection'][1]['books'][1]['book'][0]['name'] = name;


The arrays may contains diffrent keys form time to time so not all data will be in 'user_collection' some data may for example be in "root key" ['genral_collections'] or something completly diffrent. Then it has to create this whole new tree. This means also that I cant use the key names as constants values for if statements and so on because that they might be diffrent every time...

Both array_merge and array_merge_recursive give me the wrong result so it seems that I have to create my own merge function. Any tip with some do's and don'ts?

Gratefull for any tips...
//Seigan
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Re: HELP - advanced array merge

Post by Stryks »

I've just had a quick scan, but I think you may be able to make things easier on yourself by rethinking the way you have structured your array.

I think something more along the lines of ...

Code: Select all

<?php
    // Create User - use user ID as base key because this is known and unique
    $bclist[111]['name'] = 'Fred';
    
    // Create Books for collection
    $booklist[221] = 'Book 1';
    $booklist[222] = 'Book 2';
    
    // Create User Collection
    $bclist[111]['collection'][] = $booklist;
    
    // Add a book to the collection
    $bclist[111]['collection'][0][223] = 'Book 3';
    
    // Add a new collection - shorthand
    $bclist[111]['collection'][] = array(224=>'Book 4', 225=>'Book 5');
    
    // Add a new user
    $bclist[112]['name'] = 'John';
    
    // Add original collection to a new user
    $bclist[112]['collection'][] = $booklist;
    
    //Array Dump
    print_r($bclist);
    echo '<br><br>';
    
    // Data retrieval
    echo 'User 111 is ' . $bclist[111]['name'] . '.<br>';
    echo 'He has ' . count($bclist[111]['collection']) . ' collections.<br>';
    echo 'His first collection has ' . count($bclist[111]['collection'][0]) . ' books.<br>';
    echo 'They are:<br>';
    foreach ($bclist[111]['collection'][0] as $book_id=>$book_name) {
        echo " - Book #$book_id - $book_name<br>";
    }
    
    echo '<br>Full Extract: <br>';
    foreach ($bclist as $user_id=>$user_data){
        echo "<br><strong>User {$user_data['name']}($user_id):</strong><br>";
        foreach($user_data['collection'] as $coll_id=>$coll_data) {
            echo "Collection $coll_id:<br>";
            foreach($coll_data as $book_id=>$book_name) {
                echo " - $book_name($book_id)<br>";
            }
        } 
    }
?>
... would be closer to how I would visualize your data in an array.

Obviously the user and book id's are just made up and would represent the primary keys from a database (I assume). I know this kind of turns the array on it's head, but in order to maintain a good accessible structure in multidimensional array, your base index of every branch needs to be the unit that has a 1 to many relationship with the child array.

So, if a single user can have more than 1 collection, then it needs to be closer to the root of the array then the collection. Multiple books in one collection, collection closer to the root than books.

Of course, if this is just to produce a list of collections regardless of user, then this approach isn't so hot, but that isn't the impression I get from your post.

You could probably leave the padding descriptive indexes like ['books'] and ['book'] but unless you are listing non-book entities, it's not really needed.

Anyhow ... hope this helps you out.
seigan
Forum Newbie
Posts: 7
Joined: Sat Sep 27, 2008 7:23 am

Re: HELP - advanced array merge

Post by seigan »

Thansk or your answer.

I would love to chage the array structure completly but I can't. The problem is that I need to have a array strukture that fits in to a xml_writer function and it uses that type of structure. Therefore you have this weird ['books'][0]['book'] structure...
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Re: HELP - advanced array merge

Post by Stryks »

Well .. then it gets messy an frankly, not a lot of fun.

I dunno ...

Code: Select all

<?php
    // Add books in $multi2 to $multi
    foreach($multi2['users_collection'][0]['books'][0]['book'] as $book_id=>$book_data) {
        $multi['users_collection'][0]['books'][]['book'][0] = array('ID'=>$book_data['ID'], 'NAME'=>$book_data['NAME']);        
    }
?>
Something like that?

As for the changing key structure ... I'm not sure how you're going to get around that short of scanning to see what it is and then chose the appropriate action.

Very messy stuff, and it's too late at night for me to be thinking about it too hard about it. I'll try and check back tomorrow and see if anyone else has been able to help more. Maybe I'll have more to add.

Cheers
Post Reply