0

I have two arrays that contain nested arrays also, where I want to compare them against each other. If the value in the first array is false, I want that key removed from the 2nd array.

1st array: $arrayOne:

'entities' => [
        'number' => false,
        'items' => [
            [
               'name' => false, 
            ],
        ],
        'totals' => [
            'gross' => true,
            'tax' => [
                'amount' => true,
            ],
        ]
];

Then, I have the second array $arrayTwo:

'entities' => [
        'number' => '8000000',
        'items' => [
            [
               'name' => 'Bolt cutter', 
            ],
            [
               'name' => 'Wire cutter', 
            ],
        ],
        'totals' => [
            'gross' => 120.52,
            'tax' => [
                'amount' => 90.21,
            ],
        ]
];

As you can see in the first array, the keys: number and items.name is false. These two keys should not be in the final array, thus making it look like this:

'entities' => [
        'items' => [],
        'totals' => [
            'gross' => 120.52,
            'tax' => [],
        ]
];

How can I accomplish this with nested arrays? I have managed to do it for the "1st level" of the array using below:


foreach ($arrayOne as $key => $entity) {

       if ($entity === false) {
           unset($arrayTwo[$key]);
       }
}

However, as said, this only handles the first level of the array and not the nested array(s).

9
  • Can you post the structure of the final array you are trying to compare? Are they retrieve with Laravel eloquent or Laravel Colleciton? I want to know if there is any underlying method you could use for this. Commented Sep 8, 2020 at 18:43
  • The final array is shared in my OP. They are retrieved with Laravel Collection :) Commented Sep 8, 2020 at 18:44
  • I mean, does your second array may contain multiple entities? If it's exactly as you said, one of the answer should work. But if you get multiple entities in the second array and each of them need to be filtered, this is another problem. I tried the first answer work as you asked. The second one eliminated the tax array, but this could be fix. So this is why I'm trying to see where is the problem. Commented Sep 8, 2020 at 19:00
  • @ElieMorin Ah I see! Yes, the second (and nested array in general) can contain multiple entities - and I guess that is why the first answer does not work (it does work if it doesn't contain multiple entities) Commented Sep 8, 2020 at 19:02
  • Well, in that case, you should edit your question so we can be able to help you properly Commented Sep 8, 2020 at 19:04

1 Answer 1

2

i did test this, and it will work fine.

use Illuminate\Support\Arr;

$flattened_array1 = Arr::dot($array1);
$flattened_array2 = Arr::dot($array2);



foreach ($flattened_array1 as $key => $entity) {

   if ($entity === false) {
        // remove all number key from first array
        $filteredKey = preg_replace('/[0-9]+\./', '', $key);
        foreach ($flattened_array2 as $key2 => $value2) {
            if(preg_replace('/[0-9]+\./', '', $key2) == $filteredKey){
                // comparing to removed number key version of second array
               unset($flattened_array2[$key2]);
            }
        }
   }
}


// undot the array
$final_array = [];
foreach ($flattened_array2 as $key => $value) {
    array_set($final_array , $key, $value);
}

new Update to support empty array when nested array


use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

$flattened_array1 = Arr::dot($array1);
$flattened_array2 = Arr::dot($array2);

// Function to check string starting 

foreach ($flattened_array1 as $key => $entity) {

   if ($entity === false) {
        // remove all number key from first array
        $removerCounter[$key] = 0;
        $filteredKey = preg_replace('/[0-9]+\./', '', $key);
        foreach ($flattened_array2 as $key2 => $value2) {
            // comparing to removed number key version of second array
            if(preg_replace('/[0-9]+\./', '', $key2) == $filteredKey){


                // check if it contain filtered number key then
                if(preg_replace('/[0-9]+\./', '', $key2) != $key2){
                    $currentKey = $key2;
                    preg_match_all("/[0-9]+\./", $currentKey, $hits);
                    if(!isset($hits[0]) || empty($hits[0]) ){
                        break;
                    }

                    $needle = $hits[0] [ count($hits[0]) - 1 ];
                    // it is inside key not at the begining
                    if(stripos($currentKey, $needle) != 0){
                        // if parent key has no child so let it be empty array
                        $parentKey = trim(substr($currentKey, 0, stripos($currentKey, $needle)), '.');

                        // search inside secound array for parentKey of this nested array
                        $searchAndFound = false;
                        foreach ($flattened_array2 as $inner_key2 => $inner_value2) {
                            if( !($searchAndFound) && $inner_key2 != $key2 && Str::startsWith($inner_key2, $parentKey) ) {
                               $searchAndFound = true;
                            }
                        }

                        if( $searchAndFound ){
                            // die("e");
                            unset($flattened_array2[$key2]);
                            $removerCounter[$key]++;
                            //remove this key and go for next key in secound array 
                            continue;
                        }

                        if($removerCounter[$key] > 0){
                            unset($flattened_array2[$key2]);
                        }
                     
                        $flattened_array2[$parentKey] = [];

                    }
                }
                else{
                    unset($flattened_array2[$key2]);
                }
            }
        }
   }
}

// undot the array
$final_array = [];
foreach ($flattened_array2 as $key => $value) {
    array_set($final_array , $key, $value);
}

it is more complated that it expected to be . but does the trick :s.

Sign up to request clarification or add additional context in comments.

8 Comments

This does not work if the nested array have multiple items. The dot notation will be: items.0.name and items.1.name etc.
ofcourse it must not, you did not mentioned this in your question. let me take a look.
My apologies! It is not in my original question. Thanks for helping me out!
If the entities.items.name is set to true, does it remove it ?
@ElieMorin no, the question says only remove item that the are set to false in first array. so i checked entity value if is false then i try to find the keys that are related to this value in second array.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.