首页 > 解决方案 > 替换php数组中的异常数字

问题描述

我在 php 中有一组数字,如下所示

[2021-06-04] => Array
                (
                    [09:15:04] => 1.51
                    [09:15:27] => 1.32
                    [09:15:46] => 14.29
                    [09:16:05] => 14.03
                    [09:18:05] => 13.97
                    [09:18:24] => 13.88
                    [09:18:42] => 13.94
                    [09:19:01] => 13.80
                    [09:19:05] => 13.86
                    [09:19:23] => 13.97
                    [09:19:41] => 6.99
                    [09:20:00] => 14.14
                    [09:20:06] => 14.08
                    [09:20:25] => 14.04
)

在上面的数组项中.. 1.51、1.32 和 6.99有点偏离,所以我想用下一个元素替换它,所以结果数组应该如下所示。

    [2021-06-04] => Array
                (
                    [09:15:04] => 14.29
                    [09:15:27] => 14.29
                    [09:15:46] => 14.29
                    [09:16:05] => 14.03
                    [09:18:05] => 13.97
                    [09:18:24] => 13.88
                    [09:18:42] => 13.94
                    [09:19:01] => 13.80
                    [09:19:05] => 13.86
                    [09:19:23] => 13.97
                    [09:19:41] => 14.14
                    [09:20:00] => 14.14
                    [09:20:06] => 14.08
                    [09:20:25] => 14.04
)

我可以使用得到数组平均值

$a = array_filter($a);
$average = array_sum($a)/count($a);
echo $average;

我尝试了类似下面的东西

foreach($arr as $key=>$val)
{
if($avg-$val) > 5)
{
$arr[$key]  = $nextactualelem; // How do I get next correct element whose $avg-$val is less than 5


}

}

Ps:嗨,是否有可能获得下一个 10 个元素的平均值.. 而不是总平均值.. 因为在较大的集合中它不能正常工作.. 因为较大的数据集范围从 10 到 30...所以 5 的差异不起作用在最初的较小值上。或者有没有其他更快的方法来做到这一点,比如下一个数字和上一个数字之间的差异..

标签: phparrays

解决方案


如果您要对正在处理的数组进行更改,那么 foreach 不是您的最佳选择。引用键很麻烦,每次运行时变量值都不是干净的。通常,如果您需要对正在迭代的数组执行某些操作,请改用 for 循环。

现在,由于您要替换这些值,因此我们有一个小问题。查看边缘情况。如果我们想反向遍历数组(这是有道理的,因为我们想用下一个值替换异常)但最后一个值是异常怎么办?倒序仍然是一个不错的选择,但我们需要确保至少最后一个值是有效的。

鉴于键是相当随意的,我们此时不能使用 for 循环。幸运的是,我们可以使用内部数组指针来移动。

$arr = [
  '09:15:04' => 1.51,
  '09:15:27' => 1.32,
  '09:15:46' => 14.29,
  '09:16:05' => 14.03,
  '09:18:05' => 13.97,
  '09:18:24' => 13.88,
  '09:18:42' => 13.94,
  '09:19:01' => 13.80,
  '09:19:05' => 13.86,
  '09:19:23' => 13.97,
  '09:19:41' => 6.99,
  '09:20:00' => 14.14,
  '09:20:06' => 14.08,
  '09:20:25' => 14.04
];

$average = array_sum($arr)/count($arr);

end($arr); // We move the pointer to the end of the array;
//... do some verification magic here
// so we have a valid starting value on the end of the array
while(prev($arr) != false) { // move one step back while we have values
    if (($average - current($arr)) > 5) {
        $key = key($arr);           // Grab the current key
        $arr[$key] = next($arr);    // replace the value with the next
        prev($arr);                 // put the pointer back in the right place
    }
}

var_dump($arr);

请注意,如果您运行此命令,则 6.99 将保留在数组中,因为它与平均值仅相差 4.71。因此,可能需要对您的条件进行一些调整。

编辑:

获取新信息我们可以尝试以下方式:

$lookup[] = end($arr); // We move the pointer to the end of the array and place it in a lookup array
//... do some varification magic here so we have a valid starting value on the end of the array
while(prev($arr) !== false) { // move one step back while we have values
    $average = array_sum($lookup)/count($lookup); // calculate the current average based on lookup
    if (abs($average - current($arr)) > 2) { // if the difference from the current average is more the 2 points
        $arr[key($arr)] = next($arr);   // replace the value with the next
        prev($arr);                 // put the pointer back in the right place
    }
    $lookup[] = current($arr); // add the current value to the average
    if (count($lookup) > 10) { // if we have more then 10 values in the lookup
        array_shift($lookup); // Shift an element off the beginning of array
    }
}

这应该可以解决问题;)


推荐阅读