0

I have an array, $arr, which looks like this:

'sdb5' => [
    'filters' => [
        (int) 11 => [
            'find' => [
                (int) 0 => (int) 569
            ],
            'exclude' => [
                (int) 0 => (int) 89,
                (int) 1 => (int) 573
            ]
        ],
        (int) 86 => [
            'find' => [
                (int) 0 => (int) 49,
                (int) 1 => (int) 522,
                (int) 2 => (int) 803
            ],
            'exclude' => [
                (int) 0 => (int) 530,
                (int) 1 => (int) 802,
                (int) 2 => (int) 511
            ]
        ]
    ]
],

I've read Delete element from multidimensional-array based on value but am struggling to understand how to delete a value in an efficient way.

For example, let's say I want to delete the value 522. I'm doing it like this:

 $remove = 522; // value to remove

 foreach ($arr as $filters) {
     foreach ($filters as $filter) {
         foreach ($filter as $single_filter) {
             foreach ($single_filter as $key => $value) {
                 if ($value == $remove) {
                     unset($key);
                 }
             }
          }
      }
  }

I couldn't work out from the above link how to do this because even though it's a multidimensional array, it doesn't have any sub-arrays like mine.

I also don't know how else to rewrite this without repeating foreach to get to the elements of the array I want. Again, I've read Avoid multiple foreach loops but cannot apply this to my array.

I am using PHP 7.x.

halfer
  • 19,824
  • 17
  • 99
  • 186
Andy
  • 5,142
  • 11
  • 58
  • 131
  • 1
    Tricky thing about arrays is that they’re not designed for this. You might be better off building this as an object that is more useful. If you just need `522` deleted and you don’t mind where, you could build a recursive loop for each array within the array. – Zoe Edwards Feb 23 '18 at 12:36
  • What do you mean by "they're not designed for this"? I thought storing multiple values in a multi-dimensional array is exactly one of the main uses of arrays in PHP (and possibly other languages)? – Andy Feb 23 '18 at 12:38
  • 1
    Sort of. Arrays aren’t very useful when you’re looking for values in the array. For example the framework Laravel uses a class called a Collection to be able to go to town on something that’s array like (https://laravel.com/docs/5.6/collections#available-methods) which might be worth looking at in your framework. I don’t know the context of what you’re doing, but if the filters were a class that you could ‘add’ and ‘remove’ from, that might be easier to manage. – Zoe Edwards Feb 23 '18 at 12:40
  • Thank you. The context is that it's a web application where a user can "find" and "exclude" filters. This array stores the filters in a session array variable (`$arr` is a shortened version of the actual name). Here the user is trying to remove a filter. So my plan was to make an ajax call to a script which would then remove the filter by the value - which would be done by removing any instances of the array value from `$arr`. It's stored in the session because it needs to persist between page re-loads. – Andy Feb 23 '18 at 12:42

3 Answers3

1

foreach() made copy of elements. Then unseting the key is not enough, because you are destroying a local variable.

You could use references & in your foreach() loops and unset like :

 foreach ($arr as &$filters) {
     foreach ($filters as &$filter) {
         foreach ($filter as &$single_filter) {
             foreach ($single_filter as $key => $value) {
                 if ($value == $remove) {
                     unset($single_filter[$key]);
                 }
             }
          }
      }
  }

Or using keys ($k1, $k2, ...) :

 foreach ($arr as $k1 => $filters) {
     foreach ($filters as $k2 => $filter) {
         foreach ($filter as $k3 => $single_filter) {
             foreach ($single_filter as $key => $value) {
                 if ($value == $remove) {
                     unset($arr[$k1][$k2][$k3][$key]);
                 }
             }
          }
      }
  }
Syscall
  • 19,327
  • 10
  • 37
  • 52
  • This is interesting - thank you. Do I have to use multiple `foreach` statements or is there a way to write it in a shorter way? When I was looking at my code it just looked very repetitive so wasn't sure if I was being "inefficient"? – Andy Feb 23 '18 at 12:36
  • @Andy Maybe [`array_search()`](https://secure.php.net/array_search) could be a more efficient way to get the key for a searched value. At least for the last loop. – Syscall Feb 23 '18 at 12:40
1

You could also write a recursive function, so you don't have to use nested foreach:

function deleteRecursive(&$array, &$value) {
  foreach($array as $key => &$subArray) {
    if(is_array($subArray)) {
      deleteRecursive($subArray, $value);
    } elseif($subArray == $value) {
      unset($array[$key]);
    }
  }
}

$valueToDelete = 522;

deleteRecursive($array, $valueToDelete);
LKKP4ThX
  • 236
  • 2
  • 6
1
function recursiveRemoval(&$array, $val)
{
    if(is_array($array))
    {
        foreach($array as $key=>&$arrayElement)
        {
            if(is_array($arrayElement))
            {
                recursiveRemoval($arrayElement, $val);
            }
            else
            {
                if($arrayElement == $val)
                {
                    unset($array[$key]);
                }
            }
        }
    }
}

Call function

recursiveRemoval($array, $value);
Pratik Mehta
  • 707
  • 8
  • 27