怎么简化这段代码

$amount = 100; //110,90,200
$arr = [98,100,100,120,150,160,183];

如上:变量$amount跟$arr进行对比,如果变量在数组中,则返回数组中的下标值;
如果变量不在数组中,先检测变量是否在哪两个值(AB)之间,如果在,则返回这AB的下标;
如果不在两个值之间,若变量小于数组的第一个值,则返回下标0;
若变量大于数组的最后的值,则返回数组长度减一。

即:
$amount = 100;    返回 [1,2];
$amount = 110;    返回 [2,3];
$amount = 90;     返回 [0];
$amount = 200;    返回 [6];

下面是我写的代码,求精简。

$key   = [];    //下标值的数组
$count = count($arr) - 1;

foreach($arr as $k => $v){
    if($amount == $v){
        $key[] = $k;
    }
}
if(empty($key)){
    foreach($arr as $k => $v){
        if($amount < $arr[0]){
            $key[] = '';
            break;
        }
    }
}
if(empty($key)){
    foreach($arr as $k => $v){
        if($amount > $arr[$count]){
            $key[] = $count;
            break;
        }
    }
}
if(empty($key)){
    foreach($arr as $k => $v){
        if($amount >= $arr[$k] && $amount < $arr[$k + 1]){
            $key[] = $k;
            $key[] = $k + 1;
        }
    }
}
var_dump($key);
阅读 3.7k
8 个回答

刚看到这一题,就想到了二分查找法, 但是有个问题是,数组元素是可以重复的,还要返回所有重复的值的index,所以,只好在找到匹配值的时候,再做个while了

<?php
$arr = [100,100,100,100,120,150,160,183,200];

function find($x,$arr){
  $low = 0;
  $len = count($arr);
  $high =$len-1;
  $result = [];
  

  
  while ($low <= $high){
    $middle = (int)round(($high + $low ) / 2);

    if($x == $arr[$middle]){
      //result = [middle]
      while($low<=$high){
        if($arr[$low] === $x){
            array_push($result,$low);
        }
        
        $low++;
        
      }
      
      break;
    } else if ($x>$arr[$middle]){
      $low = $middle+1;
    } else {
      $high = $middle-1;
    }
  }

  
  if(count($result) === 0 ){
    $result =  [$high,$low];

    if($result[0]<=0){
        return [0];
      }
      
      if($result[0] === $len-1 ){
        return [$len-1];
      }
  }
    
  return $result;
}

$d = find(100,$arr);

var_dump($d);

我写的时候是用javascript 写的,最大限度的避免使用语言的内置函数,加上php和javascript 都属于c like的语言,所以这段代码从javascript改成php 基本就是在变量前面加了个$
javascript 在线运行可以看下面
http://jsbin.com/lazuwexuji/1...

我这个版本应该是最简化的

<?php
$result = [];
foreach($arr as $index => $value) {
    if ($amount < $value) {
        $result[0] = $index;
    } else if ($amount === $value) {
        $result[0] = $index;
        break;
    } else {
        $result[] = $index;
        break;
    }
}
var_dump($result);
?>

精简后的

<?php

$amount = 110; //110,90,200
$arr = [98,100,100,120,150,160,183];
$key   = [];
$arr_length = count($arr);
for ($i=0; $i<$arr_length; $i++) {
    if($amount == $arr[$i] || (empty($key) && $amount > $arr[$i] && $i == $arr_length - 1)){
        $key[]=$i;
    }
    if(empty($key) && $amount < $arr[$i]) {
        $i-1>=0 ? array_push($key, $i-1, $i) : $key[]=$i;
        break;
    }
} 

var_dump($key);

?>
<?php
function func($amount,$arr)
{
    //若变量小于数组的第一个值,则返回下标0;
    if($arr[0] > $amount)
    {
        return [0];
    }
    
    $in = [];
    $notin = [];
    foreach($arr as $key => $value)
    {
        //如果变量在数组中,则返回数组中的下标值;
        if($value == $amount)
        {
            $in[] = $key;
        }
        //如果变量不在数组中,先检测变量是否在哪两个值(AB)之间,如果在,则返回这AB的下标;
        elseif($value > $amount)
        {
            $notin[] = $key - 1;
            $notin[] = $key;
            break;
        }
    }
    
    if(!empty($in))
    {
        return $in;
    }
    elseif(!empty($notin))
    {
        return $notin;
    }
    else
    {
        //若变量大于数组的最后的值,则返回数组长度减一。
        return [count($arr) - 1];
    }
}
$arr = [98,100,100,120,150,160,183];

var_dump(func(100,$arr),[1,2]);
var_dump(func(110,$arr),[2,3]);
var_dump(func(90,$arr),[0]);
var_dump(func(200,$arr),[6]);

与其一个个判断,不如把所有的结果都先拿到,再根据结果选择想输出的内容

$amount = 100; //110,90,200
$arr = [98, 100, 100, 120, 150, 160, 183];

$equal = [];
$contain = [];
$result = [($amount > $arr[count($arr) - 1] ? count($arr) - 2 : 0)];

foreach ($arr as $index => $value) {
  if ($amount === $value) {
    $equal[] = $index;
  } else if ($value < $amount) {
    $contain[0] = $index;
  } else if (count($contain) === 1) {
    $contain[] = $index;
  }
}

$result = count($equal) ? $equal : (count($contain) ? $contain : $result);

var_dump($result);

//在假设已经做过去重和排序的时候:

$arr = [];
$r   = rand(5,10);

for($i=0;$i<$r;$i++){
    $arr[] = rand(1,10) + ($i>1?$arr[$i-1]:0);
}
$m = rand(0,100);

// main function
$l = $c = $r = 0;
foreach( $arr as $k => $v ){
    if($v === $m){
        $c = $k; 
    }else if($v<$m){
        $l = $k;
        $r = $k+1;
    } 
}
$key = ($c||!$l ) ? [$c] : ( $r===count($arr) ? [$l] : [$l,$r] );


// test
var_dump( $arr );
var_dump( $m );
var_dump( $l );
var_dump( $c );
var_dump( $r );
var_dump( $key );

自己拿去跑一下吧

function test($amount){

        $arr = [98,100,100,120,150,160,183];
        $max = max($arr);
        $min = min($arr);
        if($amount > $max){
            return count($arr)-1;
        }
        if($amount < $min){
            return 0;
        }
        foreach($arr as $key => $val){
            if($amount == $val){
                $tmp[] = $key;

            }
        }
        if(!empty($tmp)){
            return $tmp;
        }
        foreach($arr as $key => $val){
            if($amount < $val){
                continue;
            }else{
                $tmp[] = $key;
            }
        }
        $return[] = max($tmp);
        $return[] = max($tmp)+1;
        return $return;
    }
    var_dump(test(99));
function calcIndex($value, $resource = [])
{
    if ($value < min($resource)) {
        return [0];
    } else if ($value > max($resource)) {
        return [count($resource) - 1];
    }
    $result = [];
    foreach ($resource as $index => $item) {
        if ($item == $value) {
            $result[] = $index;
        } else if ($index < count($resource) - 1 && $value > $item && $value < $resource[$index + 1]) {
            $result = [$index, $index + 1];
        }
    }
    return $result;
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题