Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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_Arrays_Sorting_Random_Numbers - Fatal编程技术网

使用PHP获取数组中无循环的最近值

使用PHP获取数组中无循环的最近值,php,arrays,sorting,random,numbers,Php,Arrays,Sorting,Random,Numbers,给定一个数组: $foo = Array( 99=>'Lowest Numbers', 123=>'Low Numbers', 456=>'High Numbers', 777=>'Highest Numbers', ); 。。。值'144',我想返回最近的低值和最近的高值,而不必遍历数组中的每个元素,因为实际数组相当大 “144”的预期结果为123=>“低数值” 我目前拥有以下代码:

给定一个数组:

   $foo = Array(
         99=>'Lowest Numbers',
        123=>'Low Numbers',
        456=>'High Numbers',
        777=>'Highest Numbers',
   );
。。。值'144',我想返回最近的低值和最近的高值,而不必遍历数组中的每个元素,因为实际数组相当大

“144”的预期结果为123=>“低数值”

我目前拥有以下代码:

    function name($color,$fuzzy=false) {
        global $resene;
        $long = 0;
        if(is_array($color)) {
            $long = Color::hex2lng(Color::rgb2hex($color));
        } else {
            $long = Color::hex2lng($color);
        }

        if(isset($resene[$long])) {
            echo $resene[$long];
        } else {
            if($fuzzy) {
                $resene[$long] = '';
                ksort($resene);

                // This is where I am having problems
                                    // The array is sorted, so it should be a simple
                                    // matter of getting the previous and next value
                                    // somehow since we know the position we want to
                                    // start at exists because it has been added.

                echo 'No color name found';
            }
        }
    }
基本上,这个概念非常简单,因为我们将未找到的值注入到数组中,我们知道它存在。按键排序,现在可以确保两个最近的键与正在搜索的数字最匹配

上述函数实际上是基于十六进制或RGB颜色的搜索,该颜色转换为基数10(长值)

数组中的键是非增量的,这意味着它不是0,1,2,3,即使我“翻转”数组,键也将是字符串,同样,没有增量来获得最接近的值

我在考虑拆分之类的东西,但是它似乎是基于数组中的元素数量拆分数组的,而不是基于键

这基本上是完成这项工作的最后一步,而不必遍历每个元素

任何帮助都将不胜感激

下面是我编写的静态函数的Pastbin,它返回一个颜色数组(),使用颜色的长值作为键,值是颜色的字符串名称

此处:

$input = 142;
$offset = 0;

while(true){
  if(isset($foo[$input - $offset])){
    $found = array($input - $offset => $foo[$input - $offset]);
    break;
  }  

  if(isset($foo[$input + $offset])){
    $found = array($input - $offset => $foo[$input + $offset]);
    break;
  }      

  $offset++;
}
它应该比标准回路便宜一点

那个阵列到底有多大?为什么速度很重要

编辑:


NVM。你的问题错了。我刚刚在100K元素的关联数组上对
ksort()
做了一个计时测试。需要0.07秒。而完整的foreach循环需要0.01秒

正如Olcat所指出的,在这里您可能不需要太担心性能,但您可以尝试二进制搜索的一种变体。无法跳过此处的搜索,因为无法切入到ksort()。这是我想到的一个简单草案:

//$resene is your input ksort()-ed array, $long is the key which position and neighbours you're trying to find
$keys = array_keys($resene);
$min = reset($keys);
$s = key($keys);   // = 0
$max = end($keys);
$e = key($keys);   // = count($resene)
do {
    $guess = $s + (int)(($long - $min)/($max - $min)*($e - $s));
    if ($keys[$guess] > $long) {
        $e = $guess - 1;
        $max = $keys[$e];
        $min = $keys[++$s];
    } elseif ($keys[$guess] < $long) {
        $s = $guess + 1;
        $min = $keys[$s];
        $max = $keys[--$e];
    }
} while ($keys[$guess] != $long && $e != $s);
echo 'Me = '.$keys[$guess].'; prev = '.$keys[$guess - 1].'; next = '.$keys[$guess + 1];
/$resene是您的输入ksort()-ed数组,$long是您试图找到的位置和邻居的关键
$keys=数组_键($resene);
$min=重置($keys);
$s=钥匙($keys);//=0
$max=结束($key);
$e=钥匙($keys);//=计数($resene)
做{
$guess=$s+(int)($long-$min)/($max-$min)*($e-$s));
如果($keys[$guess]>$long){
$e=$guess-1;
$max=$keys[$e];
$min=$keys[+$s];
}elseif($keys[$guess]<$long){
$s=$guess+1;
$min=$keys[$s];
$max=$keys[--$e];
}
}而($keys[$guess]!=$long&&$e!=$s);
回显“我=”。$keys[$guess];上一个='.$keys[$guess-1].';next='.$keys[$guess+1];
我在一个由20000个从0到5000000的随机数组成的数组上运行了一些测试,使用该数组的随机目标值,我在3-4个循环中获得了成功。当然,不要忘记检查上一个/下一个是否存在

此外,如果可以使用普通索引数组并对其使用普通排序(),以避免使用数组_keys()复制数组,则效果会更好。我猜您试图在这里使用键只是为了获得一些速度,但在数组值中没有任何有用的东西?如果是这样,您应该切换到索引数组

如果您避免使用k/sort()并使用类似的方法首先找到插入新值的位置,则可以使它工作得更好。然后,您可以使用array_splice()插入它,并且您已经知道它的位置,即prev/next

更新

在看了示例中的方法2之后,您试图做的事情变得更加清楚了。我很好奇我能在PHP中找到多少索引,所以这里有一个函数,它给出了与您相同的结果:

function fast_nearest($array, $value, $exact=false) {
    if (isset($array[$value])) {
        // If exact match found, and searching for exact (not nearest), return result.
        return array($value => $array[$value], 'exact' => true);
    } elseif ($exact || empty($array)) {
        return false;
    }
    // else
    $keys = array_keys($array);
    $min = $keys[0];
    $s = 0;
    $max = end($keys);
    $e = key($keys);
    if ($s == $e) {
        // only one element, it's closest
        return array_merge($array, array('exact' => false));
    } elseif ($value < $min) {
        return array($min => $array[$min], 'exact' => false);
    } elseif ($value > $max) {
        return array($max => $array[$max], 'exact' => false);
    }
    $result = false;
    do {
        $guess = $s + (int)(($value - $min) / ($max - $min) * ($e - $s));
        if ($guess < $s) {
            // oops, off the scale; we found it
            $result = $keys[$s];
        } elseif ($guess > $e) {
            $result = $keys[$e];
        } elseif ($keys[$guess] > $value && $keys[$guess - 1] < $value) {
            // found range
            $result = (($value - $keys[$guess - 1]) < ($keys[$guess] - $value)
                ? $keys[$guess - 1]
                : $keys[$guess]);
        } elseif ($keys[$guess] < $value && $keys[$guess + 1] > $value) {
            $result = (($value - $keys[$guess]) < ($keys[$guess + 1] - $value)
                ? $keys[$guess]
                : $keys[$guess + 1]);
        } elseif ($keys[$guess] > $value) {
            // narrowing search area
            $e = $guess - 1;
            $max = $keys[$e];
        } elseif ($keys[$guess] < $value) {
            $s = $guess + 1;
            $min = $keys[$s];
        }
    } while ($e != $s && $result === false);
    if ($result === false) {
        throw new Exception("Math laws don't work in this universe.");
    }
    return array($result => $array[$result], 'exact' => false);
}
函数fast\u最近($array,$value,$exact=false){
if(isset($array[$value])){
//如果找到精确匹配,并搜索精确(不是最近的),则返回结果。
返回数组($value=>$array[$value],'exact'=>true);
}elseif($exact | | empty($array)){
返回false;
}
//否则
$keys=数组\ U键($array);
$min=$keys[0];
$s=0;
$max=结束($key);
$e=钥匙($keys);
如果($s==$e){
//只有一个元素,它是最近的
返回数组_merge($array,array('exact'=>false));
}elseif($value<$min){
返回数组($min=>$array[$min],'exact'=>false);
}elseif($value>最大值$max){
返回数组($max=>$array[$max],'exact'=>false);
}
$result=false;
做{
$guess=$s+(int)($value-$min)/($max-$min)*($e-$s));
如果($guess<$s){
//哎呀,太离谱了,我们找到了
$result=$keys[$s];
}elseif($guess>$e){
$result=$keys[$e];
}elseif($keys[$guess]>$value&$keys[$guess-1]<$value){
//发现范围
$result=($value-$keys[$guess-1])<($keys[$guess]-$value)
?$keys[$guess-1]
:$keys[$guess]);
}elseif($keys[$guess]<$value&$keys[$guess+1]>$value){
$result=($value-$keys[$guess])<($keys[$guess+1]-$value)
?$keys[$guess]
:$keys[$guess+1]);
}elseif($keys[$guess]>$value){
//缩小搜索范围
$e=$guess-1;
$max=$keys[$e];
}elseif($keys[$guess]<$value){
$s=$guess+1;
$min=$keys[$s];
}
}而($e!=$s&&$result===false);
如果($result==false){
抛出新的异常(“数学定律在这个宇宙中不起作用。”);
}
返回数组($result=>$array[$result],'exact'=>false);
}
我在顶部编译了散落在函数中的大多数退出场景,而且我也放弃了在数组中插入一个项,因为它不会在函数之外持久存在。您可以使用
array\u splice()
at fou轻松添加它