简体   繁体   中英

Count number of non-null values in each column of a 2d array

Let's say I have an array:

[
  {0:1, 1:5, 3:null},
  {0:4, 1:null, 3:null},
  {0:null, 1:5, 3:5}
]

I want to count non-null values per associative key so that my expected output is:

[{0:2, 1:2, 3:1}]

Steps:

1) Loop over the array. You will get sub arrays.

2) Loop over sub arrays, we will get actual numerical values.

3) Prepare an array with key as numerical value in the sub arrays.

4) Every time in the inner loop, if the value exists as key in the result array.

5) If exists, increase the count.

This could be your solution:

<?php
$arr = [
  [0 => 1, 1 => 5, 3 => null],
  [0 => 4, 1 => null, 3 => 2],
  [0 => null, 1 => 5, 3 => 5]
];
$out = array();
foreach ($arr as $key => $value){
    foreach ($value as $key2 => $value2){
        $index = $value2;
        if (array_key_exists($index, $out)){
            $out[$index]++;
        } else {
            $out[$index] = 1;
        }
    }
}

echo "Original array:<br/>";
echo '<pre>';print_r($arr);echo '</pre>';

echo "Counted values:<br/>";
echo '<pre>';print_r($out);echo '</pre>';
?>

Output:

Original array:

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

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

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

)

Counted values:

Array
(
    [1] => 1
    [5] => 3
    [] => 3
    [4] => 1
    [2] => 1
)

If you want the sum of the values, although this does assume that all the arrays have the same columns as the first row...

$data = '[
  {"0":1, "1":5, "3":null},
  {"0":4, "1":null, "3":2},
  {"0":null, "1":5, "3":5}
]';

$data = json_decode($data, true);
$out = array();
foreach ( array_keys($data[0]) as $key ) {
    $out[$key] = array_sum(array_column($data, $key));
}
print_r(json_encode($out));

This looks at the first row of your data and gets a list of the columns(using array_keys() ), then it extracts the values for this column (using array_column() ) from the overall array and adds the values together (using array_sum() ).

The output is...

{"0":5,"1":10,"3":7}

Update: After question edit...

$data = '[
  {"0":1, "1":5, "3":null},
  {"0":4, "1":null, "3":null},
  {"0":null, "1":5, "3":5}
]';

$data = json_decode($data, true);
$out = array();
foreach ( array_keys($data[0]) as $key ) {
    $out[$key] = 0;
    foreach ( array_column($data, $key) as $value ) {
        if ( $value )   {
            $out[$key]++;
        }
    }
}
print_r(json_encode($out));

Outputs...

{"0":2,"1":2,"3":1}

Uses a similar principle, but just loops through each column and keeps count of ones that contain a value.

Or a shorter version...

$data = json_decode($data, true);
$out = array();
foreach ( array_keys($data[0]) as $key ) {
    $out[$key] = count(array_filter(array_column($data, $key)));
}
print_r(json_encode($out));

Try this it will find the sum even if one key exists in only one array as well. This will find both the sum and the counts.

<?php

$arr = [
  [0 => 1, 1 => 5, 3 => null],
  [0 => 4, 1 => null, 3 => null],
  [0 => null, 1 => 5, 3 => 5]
];
$out   = [];
$count = [];
foreach ( $arr as $key => $value) {
    # code...
    foreach ( $value as $k => $v) {
      if(NULL != $v) {
         $count[$k] = isset($count[$k]) ? ($count[$k] + 1) : 1;
      }

      $v       = (NULL === $v) ? 0 : $v;
      $out[$k] = isset($out[$k]) ? ($out[$k] + $v) : $v;

   }

}
echo '<pre>';
echo "Sum array is : ";
print_r($out);
echo '</pre>';

echo '<pre>';
echo "Count array is : ";
print_r($count);
echo '</pre>';

Will gives the output

Sum array is : 
Array
(
    [0] => 5
    [1] => 10
    [3] => 5
)

Count array is : 
Array
(
    [0] => 2
    [1] => 2
    [3] => 1
)

And for the input array commented below

    $arr = [ 
    [0 => null, 1 => null, 3 => null], 
    [0 => 4, 1 => null, 3 => null], 
    [0 => null, 1 => 5, 3 => 5] 
];

Will give

Sum array is : 
Array
(
    [0] => 4
    [1] => 5
    [3] => 5
)

Count array is : 
Array
(
    [0] => 1
    [1] => 1
    [3] => 1
)

If this is not what you want give the expected output for the commented array as well.

Although recursion is not strictly needed, array_walk_recursive() offers a direct path to the second level associative data.

Code: ( Demo )

$result = [];
array_walk_recursive(
    $array,
    function($v, $k) use(&$result) {
        $result[$k] = ($result[$k] ?? 0) + ($v !== null);
    }
);
var_export($result);

Otherwise, nested loops can be used to access the rows' data.

Code: ( Demo )

$result = [];
foreach ($array as $row) {
    foreach ($row as $k => $v) {
        $result[$k] = ($result[$k] ?? 0) + ($v !== null);
    }
}
var_export($result);

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