Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从数字列表中获取极值_Php_Numbers - Fatal编程技术网

Php 从数字列表中获取极值

Php 从数字列表中获取极值,php,numbers,Php,Numbers,如果我有一个这样的数字列表: 10,9,8,8,9,7,6,5,4,6,7,8,11,10,12,14,16,20,30,29,28,29,27,25,20,18,15,10,8,5,4,1 我想得到以下数字(根据本例):10,4,30,1 是否可以编写一个函数来获得这些极端值? 这些数字是图表的值,我想得到图表的峰值。是的,对于每一行中的数字,您将其与边数进行比较,就得到了边数(您需要该数字小于前后的数字)。然后把第一个数字和最后一个数字相加,它就完整了 我希望它是某种排序的数组。从数字数组

如果我有一个这样的数字列表:

10,9,8,8,9,7,6,5,4,6,7,8,11,10,12,14,16,20,30,29,28,29,27,25,20,18,15,10,8,5,4,1
我想得到以下数字(根据本例):
10,4,30,1

是否可以编写一个函数来获得这些极端值?


这些数字是图表的值,我想得到图表的峰值。

是的,对于每一行中的数字,您将其与边数进行比较,就得到了边数(您需要该数字小于前后的数字)。然后把第一个数字和最后一个数字相加,它就完整了


我希望它是某种排序的数组。

从数字数组中获取第一个和最后一个数字,然后对数组排序并获取与上次结果不同的第一个和最后一个数字。你会得到一个和你的例子一样的结果

下面是执行此操作的伪代码

输入:列表编号

//Handle exceptional cases
if listOfNumbers.length == 0
  return []
if listOfNumbers.length == 1
  return [listOfNumbers[0]]

//Pre-condition listOfNumbers.length > 1
extremes = emptyList
lastNumber = listOfNumbers[0]
isIncreasing = listOfNumbers[0] < listOfNumbers[1]
extremes.push(listOfNumbers[0])
foreach number in listOfNumbers[1...listOfNumbers.length]
  if(isIncreasing AND lastNumber > number)
    extremes.push(lastNumber)
    isIncreasing = false
  if(NOT isIncreasing AND lastNumber < number)
    extremes.push(lastNumber)
    isIncreasing = true

extremes.push(listOfNumbers.length-1) 
return extremes
//处理异常情况
如果listofNumber.length==0
返回[]
如果listofNumber.length==1
返回[ListofNumber[0]]
//前置条件列表OfNumbers.length>1
极端=空列表
lastNumber=ListOfNumber[0]
IsIncreating=ListofNumber[0]number)
极限。推送(最后一个数字)
i递增=错误
if(非递增且lastNumber<数字)
极限。推送(最后一个数字)
i递增=真
极限。推送(列表编号。长度-1)
回归极端

我认为这可以做到,尽管我还没有测试过。

我没有测试过这么多,任何分数低于3分的东西都不起作用,但这应该给你一个很好的起点

<?php

$array = array(10,9,8,8,9,7,6,5,4,6,7,8,11,10,12,14,16,20,30,29,28,29,27,25,20,18,15,10,8,5,4,1);

$extremes = array();
$last = null;
$num = count($array);
for($i=0;$i<$num - 1;$i++) {
    $curr = $array[$i];
    if($last === null) {
        $extremes[] = $curr;
        $last = $curr;
        continue;
    }

    //min
    if($last > $curr && $curr < $array[$i + 1]) {
        $extremes[] = $curr;
    }
    //maxes
    else if ($last < $curr && $curr > $array[$i + 1]) {
        $extremes[] = $curr;
    }
    if($last != $curr && $curr != $array[$i + 1]) {
        $last = $curr;
    }
}
//add last point
$extremes[] = $array[$num - 1];

print_r($extremes);

如果你想让它完全像你的列表一样,你必须对数据应用一些平滑处理,或者对检测应用一些公差。

一阶导数测试的一个变体,用于识别局部极值,识别delta符号从一个间隔交替到下一个间隔的点。如果增量从正到负,这些点将是最大值,如果增量从负到正,这些点将是最小值,但对于您的使用来说,这似乎并不重要。另外,加入端点,因为间隔被认为是开放的,并且您似乎希望将其包括在内

<?php
define('MSB_MASK', (int)(PHP_INT_MAX + 1));
$points = array(0, 0, 1, 0, -1, -2, -2, -3, -4, -3, 0, 1);
$extrema = getExtrema($points);

function getExtrema($points) {
    $extrema = array($points[0]);
    $limit= count($points)-2;
    for ($i = 0; $i < $limit; ++$i) {
        $deltai = $points[$i+1]-$points[$i];
        $deltaiplus1 = $points[$i+2]-$points[$i+1];
        if (($deltai ^ $deltaiplus1) & MSB_MASK)
            $extrema[] = $points[$i+1];
    }
    $extrema[] = $points[$limit+1];
    return $extrema;
}
?>

注意:我在ideone.com上做了一些测试,它可以工作,但可能有未检测到的问题。这同样适用于浮动

学分:这是我每一本微积分教科书中的一阶导数测试,只对离散数学做了少许修改。我们将每个点都视为临界点,因为我们不知道图的函数

编辑:在看了一个数据图之后,我想也许你只是在寻找闭合区间上的全局最大值和最小值,加上端点?如果是这样,只需使用一些简单的方法,比如
max($points)
min($points)

编辑:我以前从未有过使用xor的好机会

我的类似于

但是我把它们分为山峰和峡谷,这样我可以用它做更多的事情

我认为他的循环比我的循环干净得多,但我只是想亲自测试一下。
不要评判米伊

这个脚本只是绘制出点,并选择峰和谷,分别给它们绿色和红色。将其视为视觉辅助工具:P

<?php

$plot = array(10,9,8,8,9,7,6,5,4,6,7,8,11,10,12,14,16,20,30,29,28,29,27,25,20,18,15,10,8,5,4,1);

$res = local_extremes($plot);

function local_extremes(array $array){
    $peaks = array();
    $valleys = array();

    $peak_keys = array();
    $valley_keys = array();

    for($i = 0; $i < count($array); $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){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }else{
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }elseif($i == (count($array)-1)){
            if($more_than_last){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }else{
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }else{
            if($more_than_last && $more_than_next){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }elseif(!$more_than_last && !$more_than_next){
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }
    }

    return array("peaks" => $peaks, "valleys" => $valleys, "peak_keys" => $peak_keys, "valley_keys" => $valley_keys);
}
?>

<style type="text/css">
    .container{
        position: absolute;
    }

    .point{
        position: absolute;
        width: 4px;
        height: 4px;
        background: black;
    }

    .extreme{
        position: absolute;
        top: 5px;
    }

    .extr_low{
        background: red;
    }

    .extr_high{
        background: green;
    }
</style>

<?php

//Plot
echo "<div class='container'>";
foreach($plot as $key => $point){
    $left = ($key*10);
    $top = 400 - ($point*10);

    if(in_array($key, $res['peak_keys']) || in_array($key, $res['valley_keys'])){
        $extreme = "<div class='extreme'>$point</div>";
    }else{
        $extreme = "";
    }

    if(in_array($key, $res['peak_keys'])){
        $xc = "extr_high";
    }elseif(in_array($key, $res['valley_keys'])){
        $xc = "extr_low";
    }else{
        $xc = "";
    }

    echo "<div class='point $xc' style='left: ".$left."px; top: ".$top."px;'>$extreme</div>";
}
echo "</div>";

?>

<table>
    <tr>
        <th>&nbsp;</th>
        <th>Valley</th>
        <th>Peak</th>
    </tr>
    <tr>
        <th>Lowest</th>

        <td><?php echo min($res['valleys']); ?></td>
        <td><?php echo min($res['peaks']); ?></td>
    </tr>
    <tr>
        <th>Highest</th>
        <td><?php echo max($res['valleys']); ?></td>
        <td><?php echo max($res['peaks']); ?></td>
    </tr>
</table>


.集装箱{
位置:绝对位置;
}
.点{
位置:绝对位置;
宽度:4px;
高度:4px;
背景:黑色;
}
.极端{
位置:绝对位置;
顶部:5px;
}
.extr_low{
背景:红色;
}
.Extra_high{
背景:绿色;
}

你用什么标准来获得这些数字?你所说的极端到底是什么意思?你的“极端”是如何定义的?我假设你给出的抽取示例有某种形式的模式。愿意分享吗?你是说本地最小值和最大值吗?这将只返回全局最大值/最小值,而不是本地最大值和最小值。我和phpOh一起工作。我想我现在明白他在追求什么了,“数字创造的波浪”的最大值和最小值。john vs.john:]尽管答案正确(虽然它也会返回数字29),但你可以强制执行严格的值排序(
而不是
=
/
谢谢,现在我知道从哪里开始了:)。。是的,我想要的结果和我写的一模一样。我会试着去做:)@knittl我考虑过这一点,只是把这种方式作为一种设计选择,但你让我想到了一个我没有考虑过的bug。(1,5,5,8)将以5作为最小/最大值谢谢,我喜欢:)。。。
<?php

$plot = array(10,9,8,8,9,7,6,5,4,6,7,8,11,10,12,14,16,20,30,29,28,29,27,25,20,18,15,10,8,5,4,1);

$res = local_extremes($plot);

function local_extremes(array $array){
    $peaks = array();
    $valleys = array();

    $peak_keys = array();
    $valley_keys = array();

    for($i = 0; $i < count($array); $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){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }else{
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }elseif($i == (count($array)-1)){
            if($more_than_last){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }else{
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }else{
            if($more_than_last && $more_than_next){
                $peaks[] = $array[$i];
                $peak_keys[] = $i;
            }elseif(!$more_than_last && !$more_than_next){
                $valleys[] = $array[$i];
                $valley_keys[] = $i;
            }
        }
    }

    return array("peaks" => $peaks, "valleys" => $valleys, "peak_keys" => $peak_keys, "valley_keys" => $valley_keys);
}
?>

<style type="text/css">
    .container{
        position: absolute;
    }

    .point{
        position: absolute;
        width: 4px;
        height: 4px;
        background: black;
    }

    .extreme{
        position: absolute;
        top: 5px;
    }

    .extr_low{
        background: red;
    }

    .extr_high{
        background: green;
    }
</style>

<?php

//Plot
echo "<div class='container'>";
foreach($plot as $key => $point){
    $left = ($key*10);
    $top = 400 - ($point*10);

    if(in_array($key, $res['peak_keys']) || in_array($key, $res['valley_keys'])){
        $extreme = "<div class='extreme'>$point</div>";
    }else{
        $extreme = "";
    }

    if(in_array($key, $res['peak_keys'])){
        $xc = "extr_high";
    }elseif(in_array($key, $res['valley_keys'])){
        $xc = "extr_low";
    }else{
        $xc = "";
    }

    echo "<div class='point $xc' style='left: ".$left."px; top: ".$top."px;'>$extreme</div>";
}
echo "</div>";

?>

<table>
    <tr>
        <th>&nbsp;</th>
        <th>Valley</th>
        <th>Peak</th>
    </tr>
    <tr>
        <th>Lowest</th>

        <td><?php echo min($res['valleys']); ?></td>
        <td><?php echo min($res['peaks']); ?></td>
    </tr>
    <tr>
        <th>Highest</th>
        <td><?php echo max($res['valleys']); ?></td>
        <td><?php echo max($res['peaks']); ?></td>
    </tr>
</table>