Skip to content

[12.x] Add Arr::reduce to reduce arrays to a single value #56648

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

moe-mizrak
Copy link

Adds Arr::reduce(array $array, callable $callback, mixed $initial = null) a small, non-breaking helper that iteratively reduces an array to a single value (single accumulated result).

Sample usages:

// Count occurrences
$fruits = ['apple','banana','apple'];
$counts = Arr::reduce($fruits, function ($carry, $item) {
    $carry[$item] = ($carry[$item] ?? 0) + 1;
    return $carry;
}, []); 
// ['apple' => 2, 'banana' => 1]

// Preserve and transform keys
$items = ['x' => 10, 'y' => 20];
$double = Arr::reduce($items, fn($carry, $value, $key) => ($carry[$key] = $value * 2) && $carry, []); 
// ['x'=>20,'y'=>40]

// Sum
$total = Arr::reduce([1,2,3,4], fn($carry, $v) => $carry + $v, 0);
// 10

@browner12
Copy link
Contributor

Is there a reason you're not using the built in PHP function array_reduce for this?

https://www.php.net/manual/en/function.array-reduce.php

@shaedrich
Copy link
Contributor

I was wondering about the same thing until it hit me: You natively only have the value, not the key and would have to have a workaround for this:

        return array_reduce(
            array_keys($array),
            fn ($carry, string|int $key) => $callback($carry, $array[$key], $key),
            $initial,
        );

@moe-mizrak
Copy link
Author

moe-mizrak commented Aug 14, 2025

Is there a reason you're not using the built in PHP function array_reduce for this?

https://www.php.net/manual/en/function.array-reduce.php

As @shaedrich stated, key is missing in array_reduce. let me give some more examples where having key makes sense.

$settings = ['cache' => true, 'debug' => false];

$flipped = Arr::reduce($settings, function ($carry, $val, $key) {
    if ($key === 'debug') {
        $carry[$key] = !$val;
    } else {
        $carry[$key] = $val;
    }
    return $carry;
}, []);
// Result: ['cache' => true, 'debug' => true]

$arr1 = ['x' => 1, 'y' => 2];
$arr2 = ['y' => 3, 'z' => 4];

$merged = Arr::reduce($arr2, function ($carry, $val, $key) {
    $carry[$key] = $carry[$key] ?? $val; // preserve existing keys
    return $carry;
}, $arr1);
// Result: ['x' => 1, 'y' => 2, 'z' => 4]

$items = ['a' => 'apple', 'b' => 'banana', 'c' => 'apple'];

$counts = Arr::reduce($items, function ($carry, $item, $key) {
    $carry[$item][] = $key; // track which keys had this value
    return $carry;
}, []);
// Result: ['apple' => ['a','c'], 'banana' => ['b']]

@taylorotwell
Copy link
Member

All of the key examples could be accomplished with mapWithKeys.

@rodrigopedra
Copy link
Contributor

Some of the given examples are best suited for array_map() or array_merge().

The sum one, from the opening message, is an actual array_reduce() that only depends on the value, so using array_reduce() or the added method is irrelevant.

The other examples, where a reduction is actually done, grouping by values or counting value occurrences, can be done by reducing from an array's keys:

<?php

// Count occurrences
$fruits = ['apple','banana','apple'];

$counts = array_reduce(
    array_keys($fruits),
    function ($carry, $key) use ($fruits) {
        $carry[$fruits[$key]] = ($carry[$fruits[$key]] ?? 0) + 1;

        return $carry;
    },
    []
);

var_dump($counts);


// track which keys had this value
$items = ['a' => 'apple', 'b' => 'banana', 'c' => 'apple'];

$groups = array_reduce(
    array_keys($items),
    function ($carry, $key) use ($items) {
        $carry[$items[$key]][] = $key;

        return $carry;
    },
    []
);

var_dump($groups);

Anyway, if a helper that takes a callback which accepts both the key and value as parameters is acceptable, I think it is best to adopt @shaedrich's implementation, which leverages the native array_reduce() function and might perform better than iterating manually over the items.

@moe-mizrak moe-mizrak deleted the feat/add-reduce-to-arr branch August 14, 2025 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants