doctrine/collections

Allow ArrayCollection#filter to filter by key, value or both

Opened this issue · 5 comments

Scenario
I want be able to filter an array by key or both (key, value)

    /// DOESN"T WORK :(
    (new ArrayCollection(['italian' => 'pizza', 'turkish' => 'kebab']))
        ->filter(function($k, $v) {
            return 'turkish' === $k;
        })
    // WORKSS!1!!  
    array_filter(['italian' => 'pizza', 'turkish' => 'kebab'], function($k, $v) {
            return 'turkish' === $k;
        }, ARRAY_FILTER_USE_BOTH);

Suggested Solution
Since PHP 5.6 we are able to specify a flag on array_filter which allows to filter the element of the array by passing to the closure that filter the array, key, value or both

array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

Flag determining what arguments are sent to callback:

ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value
ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value

Default is 0 which will pass value as the only argument to callback instead.

Suggested Implementation
At the moment ArrayCollection#filter uses the default value 0 which makes the flag feature impossible to use.

-    public function filter(Closure $p)
+    public function filter(Closure $p, int $flag = 0)
    {
-        return $this->createFrom(array_filter($this->elements, $p));
+        return $this->createFrom(array_filter($this->elements, $p, $flag));
    }

Concerns
I understand that exposing lower level APIs to an higher level of abstraction is not probably a good idea. Yet, the additional feature would be useful overall to the client who uses the method

If you provide some feedback I can submit a PR

@0x13A if this can be implemented without introducing a BC break, I'd say "why not"?

Also, a benchmark is required here, due to this being performance-sensitive API for downstream consumers.

@Ocramius Thanks for the reply.

Using the default value for $flag = 0 does not introduce a BC Break as it is the default behaviour of array_filter. I will update this issue as soon as I have a PR.

@0x13A I'm suggesting to use the ARRAY_FILTER_USE_BOTH as default, whilst keeping the public API of the method unchanged.

That makes a lot of sense

Handled in #167