2011-03-05 151 views
2

我试图构建一个工具来平均PHP中多维数组的值。阵列样本:PHP:多维数组的平均值

$t[1][1]=2; 
$t[1][2]=3; 
$t[2][1]=5; 
$t[3]=6; 
$t[4][1][1]=9; 
$t[4][1][2]=10; 
$t[4][2][1]=12; 
$t[4][2][2]=13; 

也请注意,父母没有价值(因为他们有孩子)。我有这样的:

function chklevel($s) { 
    $l = explode(".",$s); 
} 

它可以给我打电话chklevel作为

chklevel("4.2.2") 

,并使其返回13的能力,但我也希望能够调用

chklevel("4") 

和(11)(4.1​​.1(9),4.1.2(10),4.2.1(12)和4.2.2(13)的平均值。

有什么想法吗?

+0

你怎么能叫'chklevel(4.2.2)'当参数不是一个字符串?这会引发错误。另外,函数chklevel还没有返回任何东西,这是故意的吗?也许我只是没有把你的问题搞好。 – Czechnology 2011-03-05 21:16:38

+0

对不起 - 更正。我可以发誓我在那里有引号。此外,它更像是一个伪代码而不是真正的代码,因为我有一个explode()来处理字符串。 – tommyvallier 2011-03-05 21:18:28

+0

确保你看到我的更新,我添加了一个数组检查(你的4.2.2例子给我带来了麻烦,因为数组没有通过(值是),所以foreach被轰炸 - 但现在已经修复) – 2011-03-05 21:29:10

回答

1

我不得不这样做在两个函数(只是因为搜索的递归性,但这里是我的出价:

function mdarray_avg($array, $level = ''){ 
    if (!is_array($array)) throw new Exception("First argument must be an array"); 
    if (!is_string($level)) throw new Exception("Second argument must be string"); 

    $ary = $array; 
    $levels = explode('.',$level); 
    foreach ($levels as $lvl){ 
    if (array_key_exists($lvl,$ary)) 
     $ary = $ary[$lvl]; 
    else 
     throw new Exception("Level {$level} doesn't exist"); 
    } 

    $numbers = _mdarray_avg($ary); 
    $sum = array_sum($numbers); 
    return ($sum > 0 ? $sum/count($numbers) : 0); 
} 

function _mdarray_avg($array){ 
    if (!is_array($array)) return array($array); 
    $numbers = array(); 
    foreach ($array as $element){ 
    if (is_array($element)) 
     $numbers = array_merge($numbers,_mdarray_avg($element)); 
    else 
     $numbers[] = $element; 
    } 
    return $numbers; 
} 

使用它,像这样:

echo "Average: ".mdarray_avg($t,'4'); // returns 11, as expected. 

哪里$t是要搜索的数组,并且'4'是您正在搜索的级别(也可以是'1','4.2'等。

此外,一个有趣的笔记,免除第二参数平均值整个阵列,在这种情况下,我回来7.5AVG(2,3,5,6,9,10,12,13)

+0

那太棒了。谢谢。 :) – tommyvallier 2011-03-05 21:28:25

+0

@tommyvallier:不是问题。还添加了另一个校验和对无效的级别(而不是默默跳过一个缺失的数组键,它会例外说该级别不存在[以前使用'6.4.2'实际上是平均'4.2'。它不会找到6级,会跳过,然后继续寻找4]) – 2011-03-05 21:32:51

0

这里是我的解决方案:

function chklevel($t) { 

    for ($i = 1; $i < func_num_args(); $i++) { 
    if (is_array($t) && isset($t[func_get_arg($i)])) 
     $t = $t[func_get_arg($i)]; 
    } 

    return GetAvg($t); 
} 

function GetAvg($arr) { 

    if (is_array($arr)) { 
    $avg = 0; 
    foreach ($arr as $v) { 
     $avg += GetAvg($v); 
    } 
    $avg /= count($arr); 

    } else if (is_numeric($arr)) { 
    $avg = $arr; 
    } 

    return $avg; 
} 

我喜欢函数调用是这样的:chklevel($t, 4,2,2);但你可以很容易地修改它的字符串:

function chklevel($t, $s) { 
    $indexes = explode(".", $s); 
    for ($i = 0; $i < count($indexes); $i++) { 
    if (is_array($t) && isset($t[$indexes[$i]])) 
     $t = $t[$indexes[$i]]; 
    } 

    return GetAvg($t); 
}