Как посчитать все значения в многомерном массиве?

Я пробовал решения многих подобных вопросов, но все они, кажется, дают мне счет для каждого массива. Итак, у меня есть следующий массив:

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 и т. Д.

Как бы я посчитал все дубликаты вместе?

3

Решение

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

Код: (демонстрация)

$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())));

Или, функциональный однострочный с оператором splat для выравнивания, а затем считать:

var_export(array_count_values(array_merge(...$array)));
4

Другие решения

Вы можете сделать это довольно легко, используя массив аккумуляторов и повторяя все элементы:

$result = [];
foreach ($data as $row) {
foreach($row as $value) {
$result[$value] = isset($result[$value]) ? $result[$value] + 1 : 1;
}
}
var_dump($result);
2

Ты можешь использовать 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
)
1
По вопросам рекламы [email protected]