it-swarm.com.ru

Суммирование значений многомерного массива по ключу без цикла

У меня есть это: 

Array (
    [0] => Array ( [f_count] => 1 [uid] => 105 ) 
    [1] => Array ( [f_count] => 0 [uid] => 106 ) 
    [2] => Array ( [f_count] => 2 [uid] => 107 ) 
    [3] => Array ( [f_count] => 0 [uid] => 108 ) 
    [4] => Array ( [f_count] => 1 [uid] => 109 ) 
    [5] => Array ( [f_count] => 0 [uid] => 110 ) 
    [6] => Array ( [f_count] => 3 [uid] => 111 )
)

Что мне нужно, это: 7 ", который является суммой столбца f_count.

Я пытался понять это пару часов. Я думал array_sum() будет работать, но не с многомерным массивом. Итак, я попытался выяснить, как изолировать f_counts с помощью unset() или сращивания или чего-либо еще, но каждое решение, похоже, включает цикл foreach. Я перепутался с array_map, array_walk и другими безрезультатно. Я не нашел функцию, которая хорошо работает с многомерными массивами.

Я бегу PHP 5.4.

Может кто-нибудь показать мне, как суммировать этот столбец без цикла foreach?

Если это поможет, значения f_count никогда не будут больше 100, а значения uid всегда будут больше 100.


В качестве альтернативы, если есть способ выполнить мой запрос по-другому, чтобы массив не был многомерным, это, очевидно, также сработало бы.

$query = "SELECT f_count, uid FROM users WHERE gid=:gid";
...
$array = $stmt->fetchAll();

Я использую PDO.

21
David

Вам нужно соединить его с array_map() , чтобы сначала выбрать столбец f_count:

array_sum(array_map(function($item) { 
    return $item['f_count']; 
}, $arr));

Конечно, внутренне это выполняет двойной цикл; просто вы не видите этого внутри кода. Вы можете использовать array_reduce() , чтобы избавиться от одного цикла:

array_reduce($arr, function(&$res, $item) {
    return $res + $item['f_count'];
}, 0);

Однако, если скорость является единственным интересом, foreach остается самым быстрым:

$sum = 0;
foreach ($arr as $item) {
    $sum += $item['f_count'];
}

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

56
Ja͢ck

В php 5.5+ вы можете просто использовать array_column и array_sum так:

 $value = array_sum(array_column($arr,'f_count'));
61
Anthony Harley

для такого типа ситуаций цикл foreach является наилучшим вариантом, но если вам нужно сделать это несколько раз на одной странице, тогда вам следует включить цикл foreach в функцию, чтобы ваш код оставался чистым

function sum_index($arr, $col_name){
    $sum = 0;
    foreach ($arr as $item) {
        $sum += $item[$col_name];
    }
    return $sum;
}

Правка

После поиска много я обнаружил, что функция array_column существует в php 5.5 +, чтобы получить все значения одного столбца в виде массива.

Для пользователей с более низкой версией Вы можете использовать следующую функцию и вызывать ее с суммой массива, если вы также хотите получить сумму всех значений.

//to get all values of single column from multidimensional array, this function exist in php 5.5 or greater.
if(!function_exists("array_column"))
{
    function array_column($array,$column_name)
    {
        return array_map(function($element) use($column_name){return $element[$column_name];}, $array);
    }
}

Если вы хотите получить все значения одного столбца, то вызовите вышеуказанную функцию следующим образом:

$newArray = array_column($array,$column_name);

Если вы хотите получить сумму всех значений одного столбца, используйте следующий код:

$newArraySum = array_sum(array_column($array,$column_name));
1
Raja Imran Qamer

В качестве альтернативы, если есть способ выполнить мой запрос по-другому, например массив не многомерен, это, очевидно, будет работать.

$query = "SELECT f_count, uid FROM users WHERE gid=:gid"; 
... 
$array = $stmt->fetchAll(); 

Я использую PDO.

Да, есть другой способ выполнить запрос по-другому. Вы можете использовать агрегатную функцию SUM , чтобы получить сумму всех f_count непосредственно в вашем запросе. Вы бы скомбинировали это с $stmt->fetchColumn(), чтобы получить значение первого столбца (который будет суммой) первой строки (которая будет единственной строкой, поскольку мы использовали статистическую функцию).

Вот пример того, как вы могли бы сделать это:

$query = "SELECT SUM(f_count) FROM users WHERE gid=:gid";
$stmt = $pdo->prepare($query);
$stmt->execute(array(':gid' => 'yoursearchvalue'));
$sum = $stmt->fetchColumn();
1
Kodos Johnson

Поскольку вы используете PHP 5.4 с PDO, может быть еще один способ сделать это (доступно в PHP 5.1+):

  • используйте функцию PDO fetchAll() с PDO::FETCH_COLUMN в качестве fetch_style, а номер столбца с 0 индексами в качестве fetch_argument.

Согласно вашему примеру, это может быть:

$query = "SELECT f_count, uid FROM users WHERE gid=:gid";
...
$array_fcount = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);

Теперь используйте функцию array_sum для суммирования значений массива:

$fcount_sum = array_sum($array_fcount);

Вы также можете ознакомиться с документацией PHP по адресу http://php.net/manual/en/pdostatement.fetchall.php

Надеюсь, это поможет, и производительность может быть лучше, чем зацикливание! Как уже упоминалось в других ответах, в PHP 5.5 и далее у вас есть функция array_column() для получения $array_fcount непосредственно из другого массива.

0
kpk