array_reduce

(PHP 4 >= 4.0.5, PHP 5, PHP 7, PHP 8)

array_reduceИтеративно сводит массив к единственному значению через callback-функцию

Описание

function array_reduce(array $array, callable $callback, mixed $initial = null): mixed

Функция array_reduce() итеративно применяет callback-функцию к элементам массива array, чем сводит массив к единственному значению.

Список параметров

array

Входной массив.

callback
function callback(mixed $carry, mixed $item): mixed
carry

Параметр содержит результирующее значение предыдущей итерации; при первой итерации содержит значение параметра initial.

item

Параметр содержит значение текущей итерации.

initial

При передаче необязательного аргумента initial функция использует значение аргумента в начале процесса, или как конечный результат, если в первом аргументе передали пустой массив.

Возвращаемые значения

Функция возвращает значение, которое вычислила.

Функция array_reduce() вернёт null, если массив пуст и не передали параметр initial.

Список изменений

Версия Описание
8.0.0 Функция теперь выдаст ошибку уровня E_WARNING, если параметр callback-функции ожидает передачу значения по ссылке.

Примеры

Пример #1 Пример сведения массива к единственному значению функцией array_reduce()

<?php

function sum($carry, $item)
{
    $carry += $item;
    return $carry;
}

function product($carry, $item)
{
    $carry *= $item;
    return $carry;
}

$a = array(1, 2, 3, 4, 5);
$x = array();

var_dump(array_reduce($a, "sum")); // int(15)
var_dump(array_reduce($a, "product", 10)); // int(1200), потому что: 10 * 1 * 2 * 3 * 4 * 5
var_dump(array_reduce($x, "sum", "Нет данных")); // string(19) "Нет данных"

?>

Смотрите также

  • array_filter() - Фильтрует элементы массива через callback-функцию
  • array_map() - Применяет callback-функцию к элементам массивов
  • array_unique() - Удаляет повторяющиеся значения из массива
  • array_count_values() - Подсчитывает количество вхождений каждого отдельного значения в массиве

Добавить

Примечания пользователей 17 notes

up
142
Hayley Watson
18 years ago
To make it clearer about what the two parameters of the callback are for, and what "reduce to a single value" actually means (using associative and commutative operators as examples may obscure this).

The first parameter to the callback is an accumulator where the result-in-progress is effectively assembled. If you supply an $initial value the accumulator starts out with that value, otherwise it starts out null.
The second parameter is where each value of the array is passed during each step of the reduction.
The return value of the callback becomes the new value of the accumulator. When the array is exhausted, array_reduce() returns accumulated value.

If you carried out the reduction by hand, you'd get something like the following lines, every one of which therefore producing the same result:
<?php
array_reduce(array(1,2,3,4), 'f',         99             );
array_reduce(array(2,3,4),   'f',       f(99,1)          );
array_reduce(array(3,4),     'f',     f(f(99,1),2)       );
array_reduce(array(4),       'f',   f(f(f(99,1),2),3)    );
array_reduce(array(),        'f', f(f(f(f(99,1),2),3),4) );
f(f(f(f(99,1),2),3),4)
?>

If you made function f($v,$w){return "f($v,$w)";} the last line would be the literal result.

A PHP implementation might therefore look something like this (less details like error checking and so on):
<?php
function array_reduce($array, $callback, $initial=null)
{
    $acc = $initial;
    foreach($array as $a)
        $acc = $callback($acc, $a);
    return $acc;
}
?>
up
75
directrix1 at gmail dot com
10 years ago
So, if you were wondering how to use this where key and value are passed in to the function. I've had success with the following (this example generates formatted html attributes from an associative array of attribute => value pairs):

<?php

    // Attribute List
    $attribs = [
        'name' => 'first_name',
        'value' => 'Edward'
    ];

    // Attribute string formatted for use inside HTML element
    $formatted_attribs = array_reduce(
        array_keys($attribs),                       // We pass in the array_keys instead of the array here
        function ($carry, $key) use ($attribs) {    // ... then we 'use' the actual array here
            return $carry . ' ' . $key . '="' . htmlspecialchars( $attribs[$key] ) . '"';
        },
        ''
    );

echo $formatted_attribs;

?>

This will output:
 name="first_name" value="Edward"
up
62
souzacomprog at gmail dot com
6 years ago
Sometimes we need to go through an array and group the indexes so that it is easier and easier to extract them in the iteration.

<?php

$people = [
    ['id' => 1, 'name' => 'Hayley'],
    ['id' => 2, 'name' => 'Jack', 'dad' => 1],
    ['id' => 3, 'name' => 'Linus', 'dad'=> 4],
    ['id' => 4, 'name' => 'Peter' ],
    ['id' => 5, 'name' => 'Tom', 'dad' => 4],
];

$family = array_reduce($people, function($accumulator, $item) {
    // if you don't have a dad you are probably a dad
    if (!isset($item['dad'])) {
        $id = $item['id'];
        $name = $item['name'];
        // take the children if you already have 
        $children = $accumulator[$id]['children'] ?? [];
        // add dad
        $accumulator[$id] = ['id' => $id, 'name' => $name,'children' => $children];
        return $accumulator;
    }

    // add a new dad if you haven't already 
    $dad = $item['dad'];
    if (!isset($accumulator[$dad])) {
        // how did you find the dad will first add only with children 
        $accumulator[$dad] = ['children' => [$item]];
        return $accumulator;
    }

    //  add a son to his dad who has already been added
    //  by the first or second conditional "if"
    
    $accumulator[$dad]['children'][] = $item;
    return $accumulator;
}, []);

var_export(array_values($family));

?>

OUTPUT

array (
  0 =>
  array (
    'id' => 1,
    'name' => 'Hayley',
    'children' =>
    array (
      0 =>
      array (
        'id' => 2,
        'name' => 'Jack',
        'dad' => 1,
      ),
    ),
  ),
  1 =>
  array (
    'id' => 4,
    'name' => 'Peter',
    'children' =>
    array (
      0 =>
      array (
        'id' => 3,
        'name' => 'Linus',
        'dad' => 4,
      ),
      1 =>
      array (
        'id' => 5,
        'name' => 'Tom',
        'dad' => 4,
      ),
    ),
  ),
)

<?php
$array = [
  [
    "menu_id" => "1",
    "menu_name" => "Clients",
    "submenu_name" => "Add",
    "submenu_link" => "clients/add"
  ],
  [
    "menu_id" => "1",
    "menu_name" => "Clients",
    "submenu_name" => "List",
    "submenu_link" => "clients"
  ],
  [
    "menu_id" => "2",
    "menu_name" => "Products",
    "submenu_name" => "List",
    "submenu_link" => "products"
  ],
];

//Grouping submenus to their menus

$menu =  array_reduce($array, function($accumulator, $item){
  $index = $item['menu_name'];

  if (!isset($accumulator[$index])) {
    $accumulator[$index] = [
      'menu_id' => $item['menu_id'],
      'menu_name' => $item['menu_name'],
      'submenu' => []    
    ];
  }

  $accumulator[$index]['submenu'][] = [
    'submenu_name' => $item['submenu_name'],
    'submenu_link' => $item['submenu_link']
  ];

  return $accumulator