如何计算多维数组中的所有值?

3

我尝试了许多类似问题的解决方案,但它们似乎都只给出每个数组的计数。因此,我的数组如下:

Array
(
    [1] => Array
        (
            [0] => 1
            [1] => 12
            [2] => 2
        )

    [2] => Array
        (
            [0] => 1
            [1] => 13
            [2] => 3
        )

    [3] => Array
        (
            [0] => 1
            [1] => 12
            [2] => 2
        )

    [4] => Array
        (
            [0] => 1
        )

    [5] => Array
        (
            [0] => 1
        )

)

我将尝试统计所有数组中的重复项。因此输出应该显示:
Five 1's
Two 12's
One 13
Two 2's

目前我正在尝试:

foreach($data as $key => $row) {
    print_r(array_count_values($row));
}

这将输出每个数组的计数

Array
(
    [1] => 1
    [12] => 1
    [2] => 1
)
Array
(
    [1] => 1
    [13] => 1
    [3] => 1
)
Array
(
    [1] => 1
    [12] => 1
    [2] => 1
)
Array
(
    [1] => 1
)
Array
(
    [1] => 1
)

我也尝试过这个方法:
foreach ($data as $key => $row) {
    $counts = array_count_values(array_column($data, $key));
    var_dump($counts);
}

似乎缺少很多信息,比如1的数量计数。
array(2) {
  [12]=>
  int(2)
  [13]=>
  int(1)
}
array(2) {
  [2]=>
  int(2)
  [3]=>
  int(1)
}
array(0) {
}
array(0) {
}
array(0) {
}

需要注意的是,初始数组键值不一定连续,因为它代表行号。因此,该数组可能包含1、2、5、6、7等行。

如何将所有重复项一起计数?


1
请始终从var_export()调用中发布数组数据,以帮助志愿者更快地支持您。 - mickmackusa
谢谢,以后会注意的,之前不知道这些函数。 - katie hudson
3个回答

4

如果你的数组没有被展平,那么你需要访问每个值并进行增量操作,除非你想调用合并函数。

代码: (演示)

$array = [
    1 => [1, 12, 2],
    2 => [1, 13, 3],
    3 => [1, 12, 2],
    4 => [1],
    5 => [1]
];

//           make the generated value available outside of function scope
//           \-------------------------------v--------------------------/
array_walk_recursive($array, function($v)use(&$output) {  // visit each leafnode
    if (isset($output[$v])) {  // check if the key has occurred before
        ++$output[$v];         // increment
    } else {
        $output[$v] = 1;       // declare as 1 on first occurrence
    }
});

var_export($output);

输出:

array (
  1 => 5,
  12 => 2,
  2 => 2,
  13 => 1,
  3 => 1,
)

或者,非递归方式实现:
foreach ($array as $row) {
    foreach ($row as $v) {
        if (isset($output[$v])) { // check if the key has occurred before
            ++$output[$v];        // increment
        } else {
            $output[$v] = 1;      // declare as 1 on first occurrence
        }
    }
}

或者,将其压平并计数的功能性一行代码:
var_export(array_count_values(array_reduce($array, 'array_merge', array())));

或者,使用展开运算符的功能性一行代码来扁平化然后计数:
var_export(array_count_values(array_merge(...$array)));

我认为这个想法更适合我的情况,谢谢。 - katie hudson

2
你可以通过使用累加器数组并迭代所有元素来轻松完成此操作:
$result = [];
foreach ($data as $row) {
    foreach($row as $value) {
        $result[$value] = isset($result[$value]) ? $result[$value] + 1 : 1;
    }
}
var_dump($result);

哇,我想我在想得太多了!谢谢。 - katie hudson
1
绝对避免发布生成通知的代码(人们会复制粘贴这些东西)。 - mickmackusa
请不要假设研究人员具有一定的开发技能水平。请始终发布您最好的代码。如果您知道有更好的编码方式,请始终发布该方式。这将有助于使此网站更有价值,并帮助您在长期内获得更多积分。 - mickmackusa

1
你可以使用call_user_func_array合并所有单独的数组,然后在该结果上运行array_count_values
$data = array
(array(1, 12, 2),
 array(1, 13, 3),
 array(1, 12, 2),
 array(1),
 array(1)
 );

print_r(array_count_values(call_user_func_array('array_merge', $data)));

输出:

Array
(
    [1] => 5
    [12] => 2
    [2] => 2
    [13] => 1
    [3] => 1
)

首先展平也是个好主意。我正准备把这个加入我的解决方案列表。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接