Jump to content

How to manipulate multi-dimension array in PHP?


Go to solution Solved by Barand,

Recommended Posts

Hello guys, I have a multidimensional array and I want to change it to my final array. Below is the array I have.

$test = array(
            array(
                "supplier" => "TEST DEPO",
                "rolanID" => array(123, 234, 456),
                "itemCount" => 3
            ),
            array(
                "supplier" => "ANOTHER DEPO",
                "rolanID" => array(123, 786, 345),
                "itemCount" => 3
            ),
            array(
                "supplier" => "ROLAN",
                "rolanID" => array(123, 234),
                "itemCount" => 2
            ),
            
        );

So, with this array I want to output like the below array. As we can see, if all rolanID is equal to one of the supplier then I don't want to add that array into the final array. For, an example the supplier "ROLAN" array is removed completely in the final array as its all rolanID is in the supplier "TEST DEPO" but the supplier "ANOTHER DEPO" has some rolanID that is not in the supplier "TEST DEPO" so, it is included that in the final array.

Array
(
    [0] => Array
        (
            [supplier] => TEST DEPO
            [rolanID] => Array
                (
                    [0] => 123
                    [1] => 234
                    [2] => 456
                )

            [itemCount] => 3
        )

    [1] => Array
        (
            [supplier] => ANOTHER DEPO
            [rolanID] => Array
                (
                    [0] => 786
                    [1] => 345
                )

            [itemCount] => 2
        )

)

 

Edited by soyaslim

Start with a blank array where you'll hold all the previous rolanIDs that you have "seen" associated with other suppliers.

Then loop through your $test array. For each supplier, look at each of their rolanIDs. If the value exists in the "seen" array then unset it in the supplier's array. If not then add it to the "seen" array.
When you've looked through a supplier's rolanIDs, check if that array is now empty (because you removed everything in it). If so, remove the entire supplier from your $test array.

Questions? Try writing code for that. If you have problems, post the code you've written so far and tell us about what's going wrong.

On 8/12/2022 at 5:05 PM, requinix said:

Start with a blank array where you'll hold all the previous rolanIDs that you have "seen" associated with other suppliers.

Then loop through your $test array. For each supplier, look at each of their rolanIDs. If the value exists in the "seen" array then unset it in the supplier's array. If not then add it to the "seen" array.
When you've looked through a supplier's rolanIDs, check if that array is now empty (because you removed everything in it). If so, remove the entire supplier from your $test array.

Questions? Try writing code for that. If you have problems, post the code you've written so far and tell us about what's going wrong.

$finalArray[] = $test[0];
            for ($i=1; $i<count($test); $i++) {
                $id = array_diff($test[$i]['rolanID'], $test[0]['rolanID']);

                if (!empty($id)) {
                    array_push($finalArray, array(
                        'supplier' => $test[$i]['supplier'],
                        'rolanID' => $id,
                        'address' => $test[$i]['address'],
                        'itemCount' => count($id),
                    ));
                } 
            }

This is how I tried but it does not work in some cases. For example, it only checks the first element of array with others. So, there will be multiple arrays with same rolanID that doesnot exists in first element of array.

Here's my solution

    $seen = [];
    foreach ($test as $k => &$rec) {
        $rec['rolanID'] = array_diff($rec['rolanID'], $seen);          // find new ids 
        if ($rec['rolanID']) {                                         // if there are some new ones ...
            $rec['itemCount'] = count($rec['rolanID']);                   // count them
            $seen = array_merge($seen, $rec['rolanID']);                  // add the new ones to those already seen
        }
        else unset($test[$k]);                                         // if no ids, remove the array item
    }
+-----------------------------------------------+
|                                               |
|    $test ARRAY - AFTER                        |
|                                               |
+-----------------------------------------------+
|                                               |
|     Array                                     |
|     (                                         |
|         [0] => Array                          |
|             (                                 |
|                 [supplier] => TEST DEPO       |
|                 [rolanID] => Array            |
|                     (                         |
|                         [0] => 123            |
|                         [1] => 234            |
|                         [2] => 456            |
|                     )                         |
|                                               |
|                 [itemCount] => 3              |
|             )                                 |
|                                               |
|         [1] => Array                          |
|             (                                 |
|                 [supplier] => ANOTHER DEPO    |
|                 [rolanID] => Array            |
|                     (                         |
|                         [1] => 786            |
|                         [2] => 345            |
|                     )                         |
|                                               |
|                 [itemCount] => 2              |
|             )                                 |
|     )                                         |
|                                               |
+-----------------------------------------------+

 

58 minutes ago, Barand said:

Here's my solution

    $seen = [];
    foreach ($test as $k => &$rec) {
        $rec['rolanID'] = array_diff($rec['rolanID'], $seen);          // find new ids 
        if ($rec['rolanID']) {                                         // if there are some new ones ...
            $rec['itemCount'] = count($rec['rolanID']);                   // count them
            $seen = array_merge($seen, $rec['rolanID']);                  // add the new ones to those already seen
        }
        else unset($test[$k]);                                         // if no ids, remove the array item
    }
+-----------------------------------------------+
|                                               |
|    $test ARRAY - AFTER                        |
|                                               |
+-----------------------------------------------+
|                                               |
|     Array                                     |
|     (                                         |
|         [0] => Array                          |
|             (                                 |
|                 [supplier] => TEST DEPO       |
|                 [rolanID] => Array            |
|                     (                         |
|                         [0] => 123            |
|                         [1] => 234            |
|                         [2] => 456            |
|                     )                         |
|                                               |
|                 [itemCount] => 3              |
|             )                                 |
|                                               |
|         [1] => Array                          |
|             (                                 |
|                 [supplier] => ANOTHER DEPO    |
|                 [rolanID] => Array            |
|                     (                         |
|                         [1] => 786            |
|                         [2] => 345            |
|                     )                         |
|                                               |
|                 [itemCount] => 2              |
|             )                                 |
|     )                                         |
|                                               |
+-----------------------------------------------+

 

Hi Barand, Could u shed a light on me? I used ur code with another case of data but there was a duplicate rolanID in one of the array.
 

$test = array(
        array(
            "supplier" => "ROLAN",
            "rolanID" => array(456),
            "itemCount" => 1,
        ),
        array(
            "supplier" => "ROLAN",
            "rolanID" => array(123, 234),
            "itemCount" => 2,
        ),
        array(
            "supplier" => "TEST DEPO",
            "rolanID" => array(123, 234, 456),
            "itemCount" => 3,
        ),
        array(  
            "supplier" => "DIFFERENT DEPO",
            "rolanID" => array(897, 487, 100),
            "itemCount" => 3,
        ),
        array(
            "supplier" => "TEST2 DEPO",
            "rolanID" => array(456, 188, 200, 123),
            "itemCount" => 4,
        )
    );

So, I tried using this data and the output was below using ur code.

Array
(
    [0] => Array
        (
            [supplier] => TEST2 DEPO
            [rolanID] => Array
                (
                    [0] => 456
                    [1] => 188
                    [2] => 200
                    [3] => 123
                )

            [itemCount] => 4
        )

    [1] => Array
        (
            [supplier] => DIFFERENT DEPO
            [rolanID] => Array
                (
                    [0] => 897
                    [1] => 487
                    [2] => 100
                )

            [itemCount] => 3
        )

    [2] => Array
        (
            [supplier] => TEST DEPO
            [rolanID] => Array
                (
                    [0] => 123
                    [1] => 234
                    [2] => 456
                )

            [itemCount] => 3
        )

)

Since the supplier 'TEST2 DEPO' has already rolanID '123' so, is it possible to remove the duplication in any other supplier? For example in this case, the rolan ID '123' is duplicated in last element of array supplier 'TEST DEPO'. 

Using your new $test array with my code, I get this in the $test array...

Array
(
    [0] => Array
        (
            [supplier] => ROLAN
            [rolanID] => Array
                (
                    [0] => 456
                )

            [itemCount] => 1
        )

    [1] => Array
        (
            [supplier] => ROLAN
            [rolanID] => Array
                (
                    [0] => 123
                    [1] => 234
                )

            [itemCount] => 2
        )

    [3] => Array
        (
            [supplier] => DIFFERENT DEPO
            [rolanID] => Array
                (
                    [0] => 897
                    [1] => 487
                    [2] => 100
                )

            [itemCount] => 3
        )

    [4] => Array
        (
            [supplier] => TEST2 DEPO
            [rolanID] => Array
                (
                    [1] => 188
                    [2] => 200
                )

            [itemCount] => 2
        )

)

 

4 minutes ago, Barand said:

Using your new $test array with my code, I get this in the $test array...

Array
(
    [0] => Array
        (
            [supplier] => ROLAN
            [rolanID] => Array
                (
                    [0] => 456
                )

            [itemCount] => 1
        )

    [1] => Array
        (
            [supplier] => ROLAN
            [rolanID] => Array
                (
                    [0] => 123
                    [1] => 234
                )

            [itemCount] => 2
        )

    [3] => Array
        (
            [supplier] => DIFFERENT DEPO
            [rolanID] => Array
                (
                    [0] => 897
                    [1] => 487
                    [2] => 100
                )

            [itemCount] => 3
        )

    [4] => Array
        (
            [supplier] => TEST2 DEPO
            [rolanID] => Array
                (
                    [1] => 188
                    [2] => 200
                )

            [itemCount] => 2
        )

)

 

Sorry Barand, I actually sorted by 'itemCount' before this so I sorted the array first by following code:
 

usort($test, function ($a, $b) {
        if ($a['itemCount'] > $b['itemCount']) {
            return -1; 
        } else 
            return 1;
    });

 

  • Solution

OK - I've added the sort

    usort($test, fn($a, $b) => $b['itemCount']<=>$a['itemCount']);     // sort descending itemCount
    $seen = [];
    foreach ($test as $k => &$rec) {
        $rec['rolanID'] = array_diff($rec['rolanID'], $seen);          // find new ids 
        if ($rec['rolanID']) {                                         // if there are some new ones ...
            $rec['itemCount'] = count($rec['rolanID']);                   // count them
            $seen = array_merge($seen, $rec['rolanID']);                  // add the new ones to those already seen
        }
        else unset($test[$k]);                                         // if no ids, remove the array item
    }

and I now get this (no duplicate 123)...

Array
(
    [0] => Array
        (
            [supplier] => TEST2 DEPO
            [rolanID] => Array
                (
                    [0] => 456
                    [1] => 188
                    [2] => 200
                    [3] => 123
                )

            [itemCount] => 4
        )

    [1] => Array
        (
            [supplier] => TEST DEPO
            [rolanID] => Array
                (
                    [1] => 234
                )

            [itemCount] => 1
        )

    [2] => Array
        (
            [supplier] => DIFFERENT DEPO
            [rolanID] => Array
                (
                    [0] => 897
                    [1] => 487
                    [2] => 100
                )

            [itemCount] => 3
        )

)

 

  • Like 1
  • Thanks 1

If I reverse the array (to give the same order that your sort is giving - DIFFERENT DEPO before TEST DEPO) I get

Array
(
    [0] => Array
        (
            [supplier] => TEST2 DEPO
            [rolanID] => Array
                (
                    [0] => 456
                    [1] => 188
                    [2] => 200
                    [3] => 123
                )

            [itemCount] => 4
        )

    [1] => Array
        (
            [supplier] => DIFFERENT DEPO
            [rolanID] => Array
                (
                    [0] => 897
                    [1] => 487
                    [2] => 100
                )

            [itemCount] => 3
        )

    [2] => Array
        (
            [supplier] => TEST DEPO
            [rolanID] => Array
                (
                    [1] => 234
                )

            [itemCount] => 1
        )

)

 

Thanks a tons Brand, after I reviewed my code I found that I skip '&'  in the loop initialization. It's working perfectly and is awesome. If there is anything I can contribute as my appreciation please let me know. Also, would u recommend me php guidelines?

That probably requires some explanation.

If you have

foreach ($test as $k => $rec) {

then a copy of the array is passed in $rec. Any changes to $rec are made only to that copy.

However, with

foreach ($test as $k => &$rec) {

the address of the original array is passed (ie by reference) so any changes are made to the original array.

My main sources of learning have been

  • the manual at php.net,
  • tips picked up in these forums and via Google
  • and lots of practice/experimentation.

I often see phpdelusions.net cited as a good source.

  • Thanks 1
On 8/16/2022 at 4:47 AM, soyaslim said:

Thanks a tons Brand, after I reviewed my code I found that I skip '&'  in the loop initialization. It's working perfectly and is awesome. If there is anything I can contribute as my appreciation please let me know. Also, would u recommend me php guidelines?

I'll add to Barand's suggestions:

Most professional web development also involves the use of a framework.  The 2 most popular and active frameworks are:

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.