简体   繁体   中英

How to count and sum the occurrences in each column of an array?

I want to try to calculate the total occurrences for each "column of digits" in the following list of numbers.

8353
1619
6889
3850
7596
9594
2557
8838
6224
7075

My expected result for the first digits is:

array (
    8 => 2,  // 1st and 8th number starts with 8
    1 => 1,  // 2nd number
    6 => 2,  // 3rd and 9th
    3 => 1,  // 4th
    7 => 2,  // 5th and 10th
    9 => 1,  // 6th
    2 => 1,  // 7th
)

I need the same kind of calculation for the other columns (2nd digits, 3rd digits, 4th digits) all collected into a multi-dimensional array.

What I did so far was like this

while($rowny = mysqli_fetch_assoc($mulai)) {
    $rowData[] = $rowny;
}
for($i=0; $i<100; $i++){
    $hasil[] = $rowData[$i]['result'];

    $pecah = str_split($hasil[$i],1);
    $hitunga = array_count_values($pecah);

    print_r($hitunga);echo "<br/>";
}

So far when I print the $hitunga , it shows the array like this

Array ( [8] => 1 [3] => 2 [5] => 1 )
Array ( [1] => 2 [6] => 1 [9] => 1 )
Array ( [6] => 1 [8] => 2 [9] => 1 )
Array ( [3] => 1 [8] => 1 [5] => 1 [0] => 1 )
Array ( [7] => 1 [5] => 1 [9] => 1 [6] => 1 )
Array ( [9] => 2 [5] => 1 [4] => 1 )
Array ( [2] => 1 [5] => 2 [7] => 1 )
Array ( [8] => 3 [3] => 1 )
Array ( [6] => 1 [2] => 2 [4] => 1 )
Array ( [7] => 2 [0] => 1 [5] => 1 )

but this is changing the order of the digits and in some cases there are no numbers in the latter columns. I expect to maintain 4 columns of numbers and get the total occurrences in each column.

  1. Split each number into a 4-element array.
    ( array_map('str_split', $numbers) )
  2. Transpose the new multi-dimensional structure, IOW -- convert columns to rows.
    ( array_map(null, ...#1) )
  3. Count the values.
    ( array_map('array_count_values', #2)

One-liner:

array_map('array_count_values', array_map(null, ...array_map('str_split', $numbers)))

Code: ( Demo )

var_export(
    array_map(
        'array_count_values',
        array_map(
            null,
            ...array_map(
                'str_split',
                $numbers
            )
        )
    )
);

Or if you prefer language constructs, this might be easier to comprehend...

Code: ( Demo )

$result = [];
foreach ($numbers as $number) {
    foreach (str_split($number) as $index => $digit) {
        $result[$index][$digit] = ($result[$index][$digit] ?? 0) + 1;
    }
}
var_export($result);

Output (from both snippets):

array (
  0 => 
  array (
    8 => 2,
    1 => 1,
    6 => 2,
    3 => 1,
    7 => 2,
    9 => 1,
    2 => 1,
  ),
  1 => 
  array (
    3 => 1,
    6 => 1,
    8 => 3,
    5 => 3,
    2 => 1,
    0 => 1,
  ),
  2 => 
  array (
    5 => 3,
    1 => 1,
    8 => 1,
    9 => 2,
    3 => 1,
    2 => 1,
    7 => 1,
  ),
  3 => 
  array (
    3 => 1,
    9 => 2,
    0 => 1,
    6 => 1,
    4 => 2,
    7 => 1,
    8 => 1,
    5 => 1,
  ),
)

Significantly less elegant and sophisticated, but this might be logic you're looking for?

<?php
$arr = [
    8353, 1619, 6889,3850, 7596, 9594, 2557, 8838, 6224, 7075,
];

foreach ($arr as $key => $val) {
    $split = str_split($val);
    $count[] = array_count_values($split);
}

foreach ($count as $key => $value) {
    $cleanCount[] = array_values($value);
}

// careful - numbers in table must be equal length
for ($i = 0; $i < strlen($arr[0]); $i++) {
    $result[$i] = array_sum(array_column($cleanCount, $i));
}

echo '<pre>';
print_r($result);
echo '</pre>';

Output (sum of count for each column):

Array
(
    [0] => 15
    [1] => 14
    [2] => 9
    [3] => 2
)

working demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM