PHP迭代多维数组

3
我该如何遍历这个多维数组并返回正数计数和负数计数。答案应该是1个正数和5个负数。谢谢。
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
难道不应该是5个负数和1个正数吗? - Telmo Marques
3个回答

2

你也可以使用SPLRecursiveIteratorIteratorRecursiveArrayIterator相结合,类似于这样:

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

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

在这里,$data 代表您的多维数组。 RecursiveIteratorIterator 默认仅迭代所谓的叶子节点(即没有任何子项的项目)。作为一项安全措施,我仍然加入了一个测试来检查该项目是否确实是数字值。


1
如果目标是计算未知深度的多维数组中正数和负数的数量,则构建一个递归函数。如果不是这种情况,递归函数也可以完成任务。
function countFromMultidimentionalArray($array)
{
    $positiveCount = 0;

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

    return $positiveCount;
}

我没有测试过这个代码,它只计算正数。你可以编写一个类似的函数来计算负数 或者 更有趣的是,找到一种同时计算两者的方法(也许可以使用对象?)。这只是给你一个想法,因为这似乎像是一道作业题,我不想破坏所有的乐趣 :) 编辑: 鉴于这不是一道作业题,这里提供一个更详细的解决方案,使用一个数组来保存两个值。
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;
}

这个也没有测试过。希望能有所帮助!


谢谢@TomS。虽然你的代码可能没有经过测试,但我可以向你保证它非常有效。你让我走上了正确的道路。顺便说一下,这并不是作业,只是我试图找到一个帮助我加快学习曲线的捷径。干杯! - DanielAttard
为了完整起见,我编辑了我的答案。@DanielAttard请看一下。 - Telmo Marques

0

我在递归解决方案中遇到了一些问题,因为我也在学习[如上所示将计数器设置为零会在每次递归调用时清除您当前的计数,并且当将计数作为函数参数传递时,我还没有解决引用/作用域错误]。

此外,我不得不修改您原始数组定义的符号以使我的测试工作。
A)我假设您的键是字符串文字,而不是变量或常量。因此,我添加了''包装器。如果它们是指在其他地方定义的变量,则添加'$'..
B)您需要在单个数组中用逗号分隔元素列表,我已经添加了
C)从技术上讲并不必要,但我在定义时不使用括号表示法,只有在创建后按键访问时才使用。开发人员可以自行选择,但这有助于我确定我是否(创建或使用现有的)数组元素,当我以后回到代码时。
D)不要忘记在定义数据数组后包含';',数组定义不像函数或条件代码{}结构那样自我关闭

诚然,这种方法比递归解决方案略逊一筹,但它可以通过键和值完全访问每个元素,此时您可以根据需要报告或操作值。该方法的限制是您需要知道多少级别的嵌套(因此需要多少foreach循环)。好处是将元素添加到现有数组级别不会影响循环逻辑。

<?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 );

?>

浏览器输出:

数据数组:

2011年11月18日>C>C>T = -1324.388328

2011年11月18日>C>S>T = -249.976472

2011年12月24日>C>C>T = -2523.107928

2011年12月24日>C>S>T = 103.533528

2011年12月27日>C>C>T = -4558.837928

2011年12月27日>C>S>T = -1639.376472

正数:1

负数:5


这是一个不错的直接解决方案。此外,我想就递归问题(关于在每次调用时将计数设置为零)提出一点看法,即每次调用函数时都会分配新的局部变量,它们在执行过程中并不相同。关于通过引用传递,您可以将计数变量封装在对象内并传递该对象(自动按引用传递);构建一个类并使用属性来保存计数值;或者使用 此方法 - Telmo Marques

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接