2011-12-24 2 views
4

PHP에 불규칙한 단계 범위에 대한 기존 기능이 있습니까?이 기능을 제공하는 일반적인 솔루션이 있습니까? 아니면 다음 기능을 최적화 할 수 있습니까?불규칙한 단계로 범위 생성. 최적화

첫 번째 기능은 내가 염려하는 기능입니다. 두 번째 함수는 HTML에 대한 선택 드롭 다운을 출력하는 함수의 값을 채우는 배열을 생성하는 실제 사용 사례입니다.

<?php 

function range_multistep($min, $max, Array $steps, $jmp = 10) { 
    $steps = array_unique($steps); 
    sort($steps, SORT_NUMERIC); 

    $bigstep = ($jmp > 0) ? $jmp : $jmp * -1; 

    $e = ($min > 0) ? floor(log($min, $bigstep)) : 0; 
    for (; ; $e++) { 
     foreach ($steps as $step) { 
      $jump = pow($bigstep, $e); 
      $num = $step * $jump; 
      if ($num > $max) { 
       break 2; 
      } elseif ($num >= $min) { 
       $arr[] = $num; 
      } 
     } 
    } 

    $arr = array_unique($arr); 
    sort($arr, SORT_NUMERIC); 

    return $arr; 
} 

function prices() { 
    $price_steps = range_multistep(50, 100000, array(5, 10, 25)); 

    $prev_step = 0; 
    foreach ($price_steps as $price) { 
     $price_str = '$' . $prev_step . ' - $' . ($price - 1); 
     $price_arr[] = $price_str; 
     $prev_step = $price; 
    } 
    $price_arr[] = '$' . end($price_steps) . "+"; 

    return $price_arr; 
} 

print_r(prices()); 

이전의 결과 :

Array 
(
    [0] => $0 - $49 
    [1] => $50 - $99 
    [2] => $100 - $249 
    [3] => $250 - $499 
    [4] => $500 - $999 
    [5] => $1000 - $2499 
    [6] => $2500 - $4999 
    [7] => $5000 - $9999 
    [8] => $10000 - $24999 
    [9] => $25000 - $49999 
    [10] => $50000 - $99999 
    [11] => $100000+ 
) 
+0

최소/최대 값을 기준으로 범위를 생성하고 해당 배열을 잠시 동안 foreach를 통해 실행하는 것이 더 좋을까요? –

답변

1

for 루프의 $e 증분 치는 끝이없는 루프 인 while(1)입니다.

따라서 증분자를 pow()에서 잘못 사용하면 pow을 반복 할 때마다 한 번만 곱하면됩니다. pow()을 호출하는 것은 꽤 비쌀 수 있으므로 pow 계산을 수행하면 각 반복에 곱셈이 더 잘 분산됩니다.

편집 : 다음은 반복을 통해 pow() 계산을 배포하는 함수의 변형입니다. 또한 더 적절한 변수 초기화 (반환 값이 설정되지 않은 경우), $min$max이 스왑 된 경우 알림을 표시하고 세 번째 대신 abs을 사용하고 log()에 대해 잘못된 값이 지정되면 예외가 발생하고 이름이 바뀌 었습니다 당신이 실험 느낄 경우

/** 
* @param int $min 
* @param int $max 
* @param array $steps 
* @param int $jmp 
* @return array range 
*/ 
function range_multistep($min, $max, Array $steps, $jmp = 10) { 
    $range = array(); 
    if (!$steps) return $range; 

    if ($min < $max) { 
     trigger_error(__FUNCTION__.'(): Minima and Maxima mal-aligned.', E_USER_NOTICE); 
     list($max, $min) = array($min, $max); 
    } 

    $steps = array_unique($steps); 
    sort($steps, SORT_NUMERIC); 

    $bigstep = abs($jmp); 
    if ($bigstep === 0) { 
     throw new InvalidArgumentException(sprintf('Value %d is invalid for jmp', $jmp)); 
    } 

    $initExponent = ($min > 0) ? floor(log($min, $bigstep)) : 0; 

    for ($multiplier = pow($bigstep, $initExponent); ; $multiplier *= $bigstep) { 
     foreach ($steps as $step) { 
      $num = $step * $multiplier; 
      if ($num > $max) { 
       break 2; 
      } elseif ($num >= $min) { 
       $range[$num] = 1; 
      } 
     } 
    } 

    $range = array_keys($range); 
    sort($range, SORT_NUMERIC); 

    return $range; 
} 

, 그것은 하나에 두 개의 루프 (+ foreachfor)으로 변경 수도 있습니다 : 일부 변수는 마지막에 array_unique 작업을 아끼지 키 첫째로 반환 값에 $num를 추가 그러나 코드의 가독성은 그로부터 이익을 얻지 못합니다 :

for(
    $multiplier = pow($bigstep, $initExponent), 
    $step = reset($steps) 
     ; 
    $num = $step * $multiplier, 
    $num <= $max 
     ; 
    # infinite array iterator: 
    ($step=next($steps))?: 
    (
     $step=reset($steps) 
     # with reset expression: 
     AND $multiplier *= $bigstep 
    ) 
){ 
    if ($num >= $min) 
     $range[$num] = 1; 
} 

(함수 매개 변수와 같은) 변수를 재사용하지 말고 이름을 읽는 것이 더 좋다면, 개선이 필요하다고 생각합니다.

+0

'$ jmp'와'$ jump'는 혼동 스럽지만 별도의 변수입니다. '$ min! = min ($ min, $ max)'은'$ min <$ max'보다 낫지 않습니까? 그렇다면 왜? –

+0

) 이제는 물어 보니'$ min <$ max'을 선택하겠다;) - 나는 그 부분을 빨리 끝내고 다른 것을 시도해 보았다. 나는'$ jump '도 완전히 제거했다. 대답의 문구를 점검 할 것이고, 그것은 내 실수 다. – hakre

+0

또한 매개 변수의 형 변환 배열은 오류를 발생시키지 않거나'if (! $ steps)'뒤에 코드를 실행하지 않도록하는 배열을 제공하지 않습니다. 어쩌면'if (empty ($ steps))'가 더 적합 할 수도 있습니다. –

2

반복 또한 가장 잘 곱셈으로 대체되고, 반복 곱셈이 최고의 힘에 상승으로 대체됩니다 - 당신이 한.

난이도가 낮은 입력이 $jmp = 1 또는 $min >= $max 인 경우 "방탄"동작이 필요하지 않은 것으로 가정하면 개선 할 부분이 없습니다.

+0

방탄은 필요하지 않지만 완벽하다고 느끼는 것이 좋을 것입니다. –