0

I am trying to count elements in an array separated by one or more zeroes (0).

Example:

[1,2,4,0,9,8,4,0,0,7,1,2,6]

1+2+4, 9+8+4, 7+1+1+2+6

Output: [7,21,16]

I have written the following function:

function countElementsInArray(){
    $array = [1,2,4,0,9,8,4,0,7,1,2,6];

    $countArr = [];
    $count = 0;
    $test = 0;

    for($i = 0; $i < count($array); $i++){
        if( $array[$i] != 0 ) {
           $count += $array[$i];
        } 
        //else if($array[$i] == 0 || $array[$i - 1] == 0){
        else{
            $count = 0;
            $test += 1;
        }
        $countArr[$test] = $count;
    }
    return $countArr;
}

This works fine if I have only one "0" in the array. I can't figure out how to add up the values if I have two zeroes. Any idea how to solve this problem?

EDIT: the problem is when I have array like this: [1,2,4,0,9,8,4,0,0,7,1,2,6] with two "0" next to each other: print_r(countElementsInArray())

Array ( [0] => 7 [1] => 21 [2] => 0 [3] => 16 )

and what I am trying to reach is this:

Array ( [0] => 7 [1] => 21 [2] => 16 )
5
  • Now you are confusing me: You want the output to be: Array ( [0] => 7 [1] => 21 [2] => 16 ) with this array: [3,2,1,0,5,4,0,0,8,4] ?! Commented Jun 28, 2015 at 6:10
  • Yeah, your numbers in that last example don't add up. Commented Jun 28, 2015 at 6:13
  • Sorry, I put there wrong array by mistake. Commented Jun 28, 2015 at 6:21
  • 1
    Roman, can you please provide a feedback on the offered solutions below? Commented Jun 28, 2015 at 6:33
  • @OfirBaruch, That's great solution. Answered all my issues even the legitimate sum of 0 that StuartWagner pointed out. Didn't thought about that. Commented Jun 28, 2015 at 7:05

5 Answers 5

3

In order to solve your problem with "more than one '0' in the array" you'll need to reset the sum variable when you reach a 0 value and to increase the key so it would start calculating the sum of the new subset of values.

Edit: In case that there are multiple zeros one next to the other, the code would unset that sum and start again with the same $i (key).

Edit 2: Regarding @Stuart Wagner comment, in order to make sure the code doesn't unset legit sum (like: [-2,1,1]) I added a new variable that contains the last value ($previousVal). If that value isn't 0 and the sum is 0, than it's a legit zero-sum, otherwise - not.

Edit 3: As @Rizier123 mentioned in the comment, since that on the first loop $previousVal isn't set, the main condition will return false. The solution would be to set the variable before the loop.

Edit 4: In case of a trailing zero, simply remove it from the array as it doesn't has affect (doesn't separate between subsets).

function countElementsInArray($array){

   $sumArr = array();
   $i = 0;
   $sumArr[$i] = 0;
   $previousVal = 0;

   if(last($array) == 0)
     array_pop($array);

   foreach($array as $val){
     if($val == 0){
        if($sumArr[$i] == 0 && isset($previousVal) && $previousVal == 0){
          unset($sumArr[$i]);
        } else {
          $i++;
        }
        $sumArr[$i] = 0;
     }
     $sumArr[$i] += $val;
     $previousVal = $val;
   }
   return $sumArr;
}

$array = [1,2,4,0,9,8,4,0,7,1,2,6];
print_r(countElementsInArray($array));


$array = [3,2,1,0,5,4,0,0,8,4];
print_r(countElementsInArray($array));

$array = [-2,1,1,0,5,4,0,0,8,4];
print_r(countElementsInArray($array));

$array = [0,0,0,-2, 1, 1, 0, 5, 4, 0,0,0, 0, 8, 4,0,-3,2,1];
print_r(countElementsInArray($array)); 

Output:

Array
(
    [0] => 7
    [1] => 21
    [2] => 16
)
Array
(
  [0] => 6
  [1] => 9
  [2] => 12 
)
Array
(
  [0] => 0
  [1] => 9
  [2] => 12
)
Array
(
  [0] => 0
  [1] => 9
  [2] => 12
  [3] => 0
)

Demo

Sign up to request clarification or add additional context in comments.

9 Comments

You suppressed one 0 in the input array – with the input array as shown by OP, containing two consecutive zeroes ([3,2,1,0,5,4,0,0,8,4]), your result array contains a zero “sum” as well.
Fixed by adding another condition to check the sum, if it's 0 - unset that sum and start over.
Just like with @Rizier123's answer, what if there's a legitimate sum of 0? Say, [-2,1,1]? That would not be in your output.
You're right - but I have a solution - will edit in 2 minutes.
This doesn't account for trailing zeroes, e.g. [1, 2, 4, 0].
|
1

This is rather late, but just for completeness, here's another solution that makes use of some of the best parts of the other answers, and accounts for things like leading zeroes, trailing zeroes, and zero sums. It's also the simplest, I believe.

function countSeparatedElements($array, $seperator = 0)
{
    $array[] = $seperator;
    $result = [];
    $i = 0;

    foreach ($array as $val) {
        if ($val == $seperator) {
            if (! empty($result[$i])) {
                $result[$i] = array_sum($result[$i]);
                $i++;
            }
            continue;
        }
        $result[$i][] = $val;
    }

    return ! empty($result) ? $result : false;
}

$array = [0, 1, 2, 4, 0, 9, 8, 4, 0, 0, -2, 1, 1, 0, 0, 7, 1, 2, 6, 0];
$output = countSeparatedElements($array);
print_r($output);

Output:

Array
(
    [0] => 7
    [1] => 21
    [2] => 0
    [3] => 16
)

Comments

0

This should work for you:

Here I just go through each element and add it to the $countArr. If we hit a 0 I check, if the count array only contains 0's or not. if yes I reset the count array and continue; else I array_sum() the values together and reset the array.

At the end I just check if we don't have an empty array and if not I add the last sum to the $result's array.

<?php

    function countSeparatedElements(array $array) {
        $countArr = [];

        foreach($array as $v) {
            $countArr[] = $v;
            if($v == 0) {
                if(count(array_unique($countArr)) === 1 && end($countArr) === 0) {
                    $countArr = [];
                    continue;
                } else {
                    $result[] = array_sum($countArr);
                    $countArr = [];
                }
            }

        }

        if(!empty($countArr))
            $result[] = array_sum($countArr);
        return $result; 

    }

    $array = [3, 2, 1, 0, 5, 4, 0, 0, 8, 4];
    $counts = countSeparatedElements($array);
    print_r($counts);

?>

output:

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

EDIT:

Another solution would be just to implode your string with leading commas and then explode it. After this you just can take the array_sum():

<?php

    $array = [0, 1, 2, 4, 0, 9, 8, 4, 0, 0, -2, 1, 1, 0, 0, 7, 1, 2, 6, 0];
    $str = array_reduce($array, function($keep, $v){
        return $keep .= "," . $v;
    }, "");

    $arr = preg_split("/,0/", $str, -1, PREG_SPLIT_NO_EMPTY);
    $counts = array_map(function($v){
        return array_sum(explode(",", $v));
    }, $arr);

    print_r($counts);


?>

output:

Array
(
    [0] => 7
    [1] => 21
    [2] => 0
    [3] => 16
)

2 Comments

What if there's a legitimate sum of 0? Say, [-2,1,1]? Your array_filter would remove those as well.
@StuartWagner You're right, didn't thought about that. updated my answer now and now I handle it with arrays, so to check if the array only contains 0's
0

I dont like all this loop-variable stuff much so i am going to do some regex magic:

    $array = [1,2,4,0,9,8,4,0,0,7,1,2,6,0,0,0,10,20,30,0,0,0,1,2,3,6,0,0,0,4];


function custom_count($a){

    $str = implode('|',$a); // array to string
    $str = preg_replace('/(\|0)+/','|0',$str); // repllce multiple 0's, Regey magic
    $new = explode('|',$str);

    $res = [0];
    $key = 0;
    foreach($new as $num){
        if($num == 0) {
            $key++;
            $res[$key] = 0;
        }
        else
            $res[$key] += $num;
    }
    return $res;
}

var_dump(custom_count($array));

/*
 * [0]=>
  int(7)
  [1]=>
  int(21)
  [2]=>
  int(16)
  [3]=>
  int(60)
  [4]=>
  int(12)
  [5]=>
  int(4)
}
 */

1 Comment

oh yes you are right, changed the regex, will work now
0
$res = Array_reduce($array, 
             function($c, $v) {
                if($v) { 
                   if (!$c[1]) $c[0][] = $v;
                   else $c[0][count($c[0])-1] += $v;
                   $c[1]++; }
                else $c[1] = 0;
                return $c;
             }, [[],0])[0];

Works with leading and trailing zero and empty array

$array = [0,1,2,3,0,0,-1,1,0];  // $res = array(6, 0);
$array = [];  // $res = array();

1 Comment

One of the sums in your output is 0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.