Remove elements from array equal to


[0]=>
  array {
    "id" => 11,
    "rule"=> "rule 1"
  },
[1]=>
  array {
    "id" => 40,
    "rule"=> "rule 2"
  }
[3]=>
  array {
    "id" => 55,
    "rule"=> "rule 3"
  }
[4]=>
  array {
    "id" => 40,
    "rule"=> "rule 4"
  }

How am I able to unset the elements with id = 40 to get the following array?


[0]=>
  array {
    "id" => 11,
    "rule"=> "rule 1"
  },
[1]=>
  array {
    "id" => 55,
    "rule"=> "rule 3"
  }

Do I need to do a foreach cycle / array check / unset?
Or is there any php function for it?

I have a feeling this is wrong as I am very rusty with PHP, but the right direction that you or someone else can finish off?


foreach ($array as $rule) {
if $rule['rule'] = "rule 2' then {
unset($rule['id']);
}
}

I’ve been thinking this one over for a few hours, and then it hit me. I’m trying to think of something clever… Clever, is a dangerous thing. Sometimes from a readability standpoint the most simple solution (as you described and what K.Wolfe tried to implement) is usually the best solution.

To take K.Wolfe’s code and make it workable

foreach ($rules as $key => $rule) {
  if ($rule['id'] === 40) {
    unset($rules[$key]);
  }
} 

I agree.

Here’s another way to go but you’re creating a function. I do like how the one line says it all.


function id_not_40( $v ) {
  return $v['id'] != 40;
}

$new_array = array_filter( $orig_array, "id_not_40" );

Or all in one but less readable in my opinion.


$new_array = array_filter( $orig_array, function( $v ) { return $v['id'] != 40; } );

and you may want to call array_values() on it after to re-index the array if desired.

If you going this route, then you may as well finish it off…


function id_not_in( $v, $filter ) {
  return $v['id'] != $filter;
}

$new_array = array_filter( $orig_array, "id_not_in" );

Well, now we’re getting to be complex again. :slight_smile: But for the sake of exercise…


/**
 * Filters a multi-dimentional array based on matching (or not)
 * a key/value pair of the items
 *
 * @param array $data
 * @param string $k
 * @param string $v
 * @param boolean $match
 *
 * @return array
 */
function special_array_filter( $data, $k, $v, $match = true ) {
  $filter = function ( $item ) use ( $k, $v, $match ) {
    return ( isset( $item[ $k ] ) && $item[ $k ] == $v ) ? $match : !$match;
  };

  return array_filter( $data, $filter );
}


// usage:

$orig_array = array(
  array (
    "id" => 11,
    "rule"=> "rule 1"
  ),

  array (
    "id" => 40,
    "rule"=> "rule 2"
  ),

  array (
    "id" => 55,
    "rule"=> "rule 3"
  ),

  array (
    "id" => 40,
    "rule"=> "rule 4"
  ) );

$new_array = special_array_filter( $orig_array, 'id', 40, false );

Don’t try this at home - unless you need to do something like that in more than one place. But really, just go with the foreach thing, though I do like my first array_filter solution myself.


<?php
class Filter extends FilterIterator
{
    public function accept()
    {
      $current = $this->current();
      return 40 != $current['id'];
    }
}


$array = array(
    array('id' => 12, 'name' => 'foo'),
    array('id' => 40, 'name' => 'foo'),
);


foreach(new Filter(new ArrayIterator($array)) as $item)
{
    echo $item['id'], ' - ', $item['name'], PHP_EOL;
}


/*
    12 - foo
*/

Or…


<?php
class Filter extends FilterIterator
{
    public function accept()
    {
      $current = $this->current();
      return 40 != $current['id'];
    }
}


$array = array(
    array('id' => 12, 'name' => 'foo'),
    array('id' => 40, 'name' => 'foo'),
);


$array = iterator_to_array(new Filter(new ArrayIterator($array)));

Again, not quite the easiest way to do this; but I like it.

array_filter! I knew there was a function that took a callback but earlier for the life of me I couldn’t find it! I don’t get to use it a lot so I constantly forget about it.

Now that is an interesting solution. Might fall into the “trying to be too clever” paradigm, but I could see uses for it in a much more complicated scenario.