PHP - find pivot points in an array (high and low) depending on range

$data = array(5,0,15,20,22,14,13,15,12,22,40,25);

      

enter image description here

Hi I want to traverse the above data points and find the turning points based on the range.

The way I have been doing it so far is to just take $ array [$ i] - $ [$ i-1], and if the absolute difference is greater than the range, I take it as a turning point. however - the logic is flawed, as if it moved slightly up and then backwards - it breaks the loop.

enter image description here

Down 3 values ​​should be sufficient to make X a turning point down, but since they are individually out of range, they are discarded.

Any solutions?

if($diff >= 0)
{
  $diff_up = $diff_up + $diff;
}
else
{
  $diff_down = $diff_down + abs($diff);
}


if((($diff_up-$diff_down) >=$range) && ($pivot_type != "UP"))
{
  echo "Pivot UP at : ".$current;
  break;
}
else if((($diff_down-$diff_up) >$range) && ($pivot_type != "DOWN"))
{
  echo "Pivot DOWN at : ".$current;
  break;
}

      

+3


source to share


1 answer


What you are looking for are all local lows and highs.This is a good article .

I did this (with inspiration:   get extremes from a list of numbers ):

<?php
$data = array(5,0,15,20,22,14,13,15,12,22,40,25);

function minima_and_maxima(array $array){
  $maxima = [];
  $minima = [];

  $maxima[] = $array[0];
  for($i = 1; $i < count($array) - 1; $i++){
    $more_than_last = $array[$i] > $array[$i-1];
    $more_than_next = $array[$i] > $array[$i+1];

    $next_is_equal = $array[$i] == $array[$i+1];

    if($next_is_equal) {
      continue;
    }

    if ($i == 0) {
      if ($more_than_next) {
        $maxima[] = $array[$i];
      } else {
        $minima[] = $array[$i];
      }
    } elseif ($i == count($array)-1) {
      if ($more_than_last) {
        $maxima[] = $array[$i];
      } else {
        $minima[] = $array[$i];
      }
    } else {
      if ($more_than_last && $more_than_next) {
        $maxima[] = $array[$i];
      } elseif (!$more_than_last && !$more_than_next) {
        $minima[] = $array[$i];
      }
    }
  }

  for ($i = 0; $i < count($maxima); $i++) {
    $current_maxima = $maxima[$i];
    $next_maxima    = $maxima[$i+1];

    if ($current_maxima > $next_maxima) {
      unset($maxima[$i+1]);
    }
  }

  for ($i = 0; $i < count($minima); $i++) {
    $current_minima = $minima[$i];
    $next_minima    = $minima[$i+1];

    if ($next_minima < $current_minima) {
      unset($minima[$i]);
    }
  }

  return [
    'maxima' => array_values($maxima),
    'minima' => array_values($minima),
  ];
}

function get_turning_points($data)
{
  $mins_and_maxs = minima_and_maxima($data);

  $turning_points = [];
  for ($i = 0; $i < count($mins_and_maxs['maxima']) - 1; $i++) {
    $turning_points[] = $mins_and_maxs['maxima'][$i];
    $turning_points[] = $mins_and_maxs['minima'][$i];
  }
  $turning_points[] = $mins_and_maxs['maxima'][count($mins_and_maxs['maxima'])-1];

  return $turning_points;
}

print_r(get_turning_points($data));

      

This gives you:



Array
(
    [0] => 5
    [1] => 0
    [2] => 22
    [3] => 12
    [4] => 40
)

      

Demo: https://eval.in/832708

Hope it helps :)

0


source







All Articles