PHP: среднее многомерного массива - PullRequest
2 голосов
/ 06 марта 2011

Я пытаюсь создать инструмент для усреднения значений из многомерного массива в 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)

Есть мысли?

Ответы [ 2 ]

1 голос
/ 06 марта 2011

Мне пришлось сделать это в двух функциях (только из-за рекурсивного характера поиска, но вот моя ставка:

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.5 ( avg (2,3,5,6,9,10,12, 13) )

0 голосов
/ 06 марта 2011

Вот мое решение:

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);
}
...