4

I have my data in ArrayObject, simply representing an array. I need to filter the data, function array_filter() would work great. However, it does not work with ArrayObject as argument. What's the best way to treat with this? Is there any standard function which handles filtering for me?

Example:

$my_data = ArrayObject(array(1,2,3));
$result = array_object_filter($my_data, function($item) { return $item !== 2; });

Is there any array_object_filter function?

Pavel S.
  • 11,892
  • 18
  • 75
  • 113
  • Can't you use a foreach loop? – Mark Eirich Jun 30 '12 at 14:28
  • Yes, I can. But it seems a bit ugly to me. I know several approaches to solve this problem, but I'd like to hear the best one. None of what I know is really clean. – Pavel S. Jun 30 '12 at 14:39
  • What do you mean by "clean"? Don't you think that array_filter() uses a loop internally? – Mark Eirich Jun 30 '12 at 17:02
  • Yes, internally. That's what I consider clean, standard library function. – Pavel S. Jun 30 '12 at 19:00
  • There simply isn't a pre-built PHP function to do what you are asking for. See the function list at http://php.net/arrayobject - that's all there is. PHP will never do everything for you. – Mark Eirich Jun 30 '12 at 19:03

3 Answers3

5

How about you export it to an actual array, and then create a new Array Object?

$my_data = new ArrayObject(array(1,2,3));
$result = new ArrayObject( 
    array_filter( (array) $my_data, function($item) { 
         return $item !== 2; 
    })
);
Berry Langerak
  • 18,561
  • 4
  • 45
  • 58
  • 1
    I did this, but it seems ugly for me. Is there anything prettier? Since it is object, I can extend it and add the filter method to it... But really nothing in standard library? – Pavel S. Jun 30 '12 at 14:41
  • @PavelS. Not that I know of, anyway. Obviously, you could indeed extend ArrayObject to a FilterableArrayObject which takes an anonymous function and takes care of the filtering. This probably is the "cleanest" solution, although I'd argue that when you're filtering, you'd end up with a different instance of the ArrayObject anyway, so this solution seems optimal. – Berry Langerak Jun 30 '12 at 15:02
2

How about subclassing the ArrayObject and adding a new method to it:

/**
 * Filters elements using a callback function.
 *
 * @param callable $callback The callback function to use
 *
 * @return self
 */
public function filter(/* callable */ $callback = null)
{
    $this->exchangeArray(array_filter($this->getArrayCopy(), $callback));
    return $this;
}
Rico Sonntag
  • 1,505
  • 1
  • 15
  • 21
0

How about this:

$my_data = new ArrayObject(array(1,2,3));
$callback = function($item) { return $item !== 2; };
$result = new ArrayObject;
foreach ($my_data as $k => $item) if ($callback($item)) $result[$k] = $item;

Alternately, you can define an array_object_filter() function yourself:

function array_object_filter($array, $callback) {
    $result = new ArrayObject;
    foreach ($array as $k => $item) if ($callback($item)) $result[$k] = $item;
    return $result;
}
Mark Eirich
  • 10,016
  • 2
  • 25
  • 27