3

How can I iterate through this multidimensional array and return the count of positive numbers and the count of negative numbers. The answer should be 1 positive and 5 negative. Thanks.

Array
(
[Nov 18, 2011] => Array
    (
        [C] => Array
            (
                [C] => Array
                    (
                        [T] => -1324.388328
                    )
                [S] => Array
                    (
                        [T] => -249.976472
                    )
            )
    )
[Dec 24, 2011] => Array
    (
        [C] => Array
            (
                [C] => Array
                    (
                        [T] => -2523.107928
                    )
                [S] => Array
                    (
                        [T] => 103.533528
                    )
            )
    )
[Dec 27, 2011] => Array
    (
        [C] => Array
            (
                [C] => Array
                    (
                        [T] => -4558.837928
                    )
                [S] => Array
                    (
                        [T] => -1639.376472
                    )
            )
    )
)
1
  • 1
    Shouldn't it be 5 negative and 1 positive? Commented Dec 30, 2011 at 5:25

3 Answers 3

2

You could also use SPL's RecursiveIteratorIterator in combination with RecursiveArrayIterator, with something like this:

$pos = $neg = 0;
foreach( new RecursiveIteratorIterator( new RecursiveArrayIterator( $data ) ) as $item )
{
    if( !is_numeric( $item ) ) continue;

    $item < 0 ? $neg++ : $pos++;
}
var_dump( $pos, $neg );

Where $data represents your multidimensional array. RecursiveIteratorIterator defaults to only iterating, what are called, the leaves (the items that don't have any children). As a safety measure I still have incorporated a test to check whether the item is indeed a numeral value.

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

Comments

1

If the objective is to count the positive and negative numbers of a multidimensional array of unknown depth, build a recursive function. If that's not the case, a recursive function will also get the job done.

function countFromMultidimentionalArray($array)
{
    $positiveCount = 0;

    foreach($array as $value)
    {
        if(is_array($value))
        {
            $positiveCount += countFromMultidimentionalArray($value);
        }
        else
        {
            if($value >= 0)
            {
                $positiveCount++;
            }
        }
    }

    return $positiveCount;
}

I didn't test this, and it only counts positive numbers. You can make a similar function that only counts the negative ones or, more interestingly, find a way of doing both in the same function (maybe using an object?). It's only just to give you an ideia, as this seems like homework and I don't want to spoil all the fun :)

EDIT: Given the fact this isn't homework, here's a more elaborate solution, using an array to hold both values.

function countFromMultidimentionalArray($array)
{
    $values = array();
    $values["positive"] = 0;
    $values["negative"] = 0;

    foreach($array as $value)
    {
        if(is_array($value))
        {
            $result += countFromMultidimentionalArray($value);
            $values["positive"] += $result["positive"];
            $values["negative"] += $result["negative"];
        }
        else
        {
            if($value >= 0)
            {
                $values["positive"]++;
            }
            else
            {
                $values["negative"]++;
            }
        }
    }

    return $values;
}

Also didn't test this one. Hope it helps!

2 Comments

Thanks @TomS. Although your code may not have been tested, I can assure you that it worked like a charm. You've got me headed down the right track. p.s. This wasn't homework, just me trying to find a shortcut to help me on the learning curve. Cheers,
For the sake of completeness I edited my answer. @DanielAttard please take a look.
0

I had some issues with a recursive solution to this since I am also learning [setting the count to zero as shown above will erase your current count on each recursive call, and I haven't solved reference / scope errors when passing counts as function arguments].

Also, I had to modify the notation of your original array definition to get my test working.
A) I assumed your keys were meant to be string literals, not variables or constants. So I added '' wrappers. If they were meant to be variables defined elsewhere, add your '$'..
B) You need to comma-separate your list of elements within a single array, which I added
C) Not technically necessary, but I do not use bracket notation while defining, only when accessing by key after creation. Developer's choice but it helps me determine if I am ( creating or using existing ) array elements when I go back to the code later.
D) Don't forget to include your ';' after defining the data array, array defs are not self-closing like function or conditional code {} structure

Admittedly, this is a slightly less robust solution than recursion, but it gives you full access to every element by key and by value, at which point you can report or manipulate values as needed. The restriction in this method is you need to know how many levels of nesting (and therefore how many foreach loops). The upshot is adding elements to existing array levels will not affect the loop logic.

<?php

  function html_pp ( $text ) // no return
  {
    // echo paragraph to browser
    echo PHP_EOL . '<p>' . Sprintf ( $text ) . '</p>' . PHP_EOL;
  }

  // Data array
  $data = Array
  (
    'Nov 18, 2011' => Array
    (
      'C' => Array
      (
        'C' => Array ( 'T' => -1324.388328 ), // comma
        'S' => Array ( 'T' => -249.976472  )
      )
    ), // comma
    'Dec 24, 2011' => Array
    (
      'C' => Array
      (
        'C' => Array ( 'T' => -2523.107928 ), // comma
        'S' => Array ( 'T' => 103.533528   )
      )
    ), // comma
    'Dec 27, 2011' => Array
    (
      'C' => Array
      (
        'C' => Array ( 'T' => -4558.837928 ), // comma
        'S' => Array ( 'T' => -1639.376472 )
      )  
    )
  ); // end array def

  // Count variables
  $positive = 0;
  $negative = 0;

  html_pp ( 'Data Array :' );

  // Loop using key => value pairs
  foreach ( $data as $i => $date ) // Iterate through date elements
  {
    foreach ( $date as $j => $c ) // Iterate through C elements
    {
      foreach ( $c as $k => $cs ) // Iterate through C/S elements
      {
        foreach ( $cs as $n => $t ) // Iterate though T elements
        {
          // echo current element nesting path and value
          html_pp ( $i . '>' . $j . '>' . $k . '>' . $n . ' = ' . $t );
          // update +- counts
          if ( $t < 0 ) { $negative += 1; }
          else          { $positive += 1; }
        }
      }
    }
  }

  html_pp ( 'Positive : ' . $positive );
  html_pp ( 'Negative : ' . $negative );

?>

Browser output:

Data Array :

Nov 18, 2011>C>C>T = -1324.388328

Nov 18, 2011>C>S>T = -249.976472

Dec 24, 2011>C>C>T = -2523.107928

Dec 24, 2011>C>S>T = 103.533528

Dec 27, 2011>C>C>T = -4558.837928

Dec 27, 2011>C>S>T = -1639.376472

Positive : 1

Negative : 5

1 Comment

This is a nice straightforward solution. Also, I just wanted to address the issue with recursion that you refer (about setting the count to zero on each call) by saying that everytime the function is called new local variables are allocated, they are not the same throughout the execution. About passing by reference, you could encapsulate your count variables inside an object and pass that object around (automatically passed by reference); build a class and use properties to hold the count values; or by using this method

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.