2010-03-26 65 views
5

我已經在這個PHP問題上困擾了大約一天。基本上,我們有24小時格式化的小時陣列和一個任意值($hour)(也是24小時制)。問題是,我們需要採取$hour,並獲得數組中的下一個可用值,從立即執行$hour的值開始。PHP:陣列中的下一個可用值,以非索引值開始

陣列可能看起來像:

$goodHours = array('8,9,10,11,12,19,20,21). 

然後小時值可能是:

$hour = 14; 

因此,我們需要一些方法來知道19是下一個最好的時機。此外,我們可能還需要獲得第二,第三或第四(等)可用值。

這個問題似乎是因爲14不是數組中的值,所以沒有可以讓我們增加到下一個值的引用索引。

爲了讓事情變得更簡單,我已經採取$goodHours和重複值幾次,這樣我就不必處理回到開始(也許沒有做到這一點的最好辦法,但速戰速決) 。

我有一種感覺,這是簡單的我很想念,但如果有人能夠擺脫一些光,我會非常感激。

埃裏克

回答

4

你可以使用一個for循環迭代這個數組,直到找到第一個比你搜索一個更大:

$goodHours = array(8,9,10,11,12,19,20,21); 
$hour = 14; 

$length = count($goodHours); 
for ($i = 0 ; $i < $length ; $i++) { 
    if ($goodHours[$i] >= $hour) { 
     echo "$i => {$goodHours[$i]}"; 
     break; 
    } 
} 

會給你:

5 => 19 



而且,爲了獲得一個後您正在尋找的項目,還有一些,你可以使用這樣的事情:

$goodHours = array(8,9,10,11,12,19,20,21); 
$hour = 14; 
$numToFind = 2; 

$firstIndex = -1; 
$length = count($goodHours); 
for ($i = 0 ; $i < $length ; $i++) { 
    if ($goodHours[$i] >= $hour) { 
     $firstIndex = $i; 
     break; 
    } 
} 

if ($firstIndex >= 0) { 
    $nbDisplayed = 0; 
    for ($i=$firstIndex ; $i<$length && $nbDisplayed<$numToFind ; $i++, $nbDisplayed++) { 
     echo "$i => {$goodHours[$i]}<br />"; 
    } 
} 

這將使您的輸出如下:

5 => 19 
6 => 20 


基本上,這裏的想法是:

  • 在數組中前進,直到找到第一項是>=到你正在尋找
    • 什麼得到的是第一環,發現
  • 時如果匹配的項目被發現
    • 環陣列上,直到其結束,
    • 或者您已經找到儘可能多的物品。
+0

我會給你一個鏡頭。非常感謝您的快速回復:) – 2010-03-26 18:19:51

+0

不客氣:-)玩得開心! – 2010-03-26 18:23:48

0

試試這個功能:

function nextValueGreaterThan($haystack, $needle, $n=1) { 
    sort($haystack); 
    foreach ($haystack as $val) { 
     if ($val >= $needle) { 
      $n--; 
      if ($n <= 0) { 
       return $val; 
      } 
     } 
    } 
} 

$goodHours = array(8,9,10,11,12,19,20,21); 
echo nextValueGreaterThan($goodHours, 14);  // 19 
echo nextValueGreaterThan($goodHours, 14, 3); // 21 
3

您也可以使用SPL FilterIterator。雖然它不是最快的解決方案,但它的優點是可以「準備」某處/任何地方的迭代器,然後將其傳遞給不必知道迭代器如何在內部工作的函數/方法,即您下一次可以傳遞一個完全不同的迭代器。

class GreaterThanFilterIterator extends FilterIterator { 
    protected $threshold; 
    public function __construct($threshold, Iterator $it) { 
    $this->threshold = $threshold; 
    parent::__construct($it); 
    } 

    public function accept() { 
    return $this->threshold < parent::current(); 
    } 
} 

function doSomething($it) { 
    // no knowledge of the FilterIterator here 
    foreach($it as $v) { 
    echo $v, "\n"; 
    } 
} 

$goodHours = array(8,9,10,11,12,19,20,21); 
$it = new GreaterThanFilterIterator(14, new ArrayIterator($goodHours)); 
doSomething($it); 

打印

19 
20 
21 
0

這裏有類似於這些的其餘部分,包括一個可選的「偏移」參數的答案,那得到你的第n個項目過去的事實上的第一個。

class GoodHours { 
    private $hours = array(8,9,10,11,12,19,20,21); 

    public function getGoodHour($hour, $offset = 0) { 
    $length = count($this->hours); 
    for ($i = 0 ; $i < $length && $this->hours[$i] < $hour ; $i++) 
     ; // do nothing 
    return $this->hours[($i + $offset) % $length]; 
    } 
} 

// some test values 

$good = new GoodHours(); 
$x = $good->getGoodHour(5); // 8 
$x = $good->getGoodHour(5,1); // 9 
$x = $good->getGoodHour(5,2); // 10 
$x = $good->getGoodHour(10); // 10 
$x = $good->getGoodHour(10,1); // 11 
$x = $good->getGoodHour(10,2); // 12 
$x = $good->getGoodHour(21); // 21 
$x = $good->getGoodHour(21,1); // 8 
$x = $good->getGoodHour(21,2); // 9 
$x = $good->getGoodHour(21); // 8 
$x = $good->getGoodHour(22,1); // 9 
$x = $good->getGoodHour(22,2); // 10 
1

由於$goodHours已經排序,這件事情很簡單:

$next = 0; 
foreach($goodHours as $test) 
    if($test > $hour && $next = $test) 
     break; 

四個班輪後(可在自然行的數量較少被寫入),$next爲0,如果$hour能不在$goodHours中匹配,或者它包含立即執行的值$hour。這就是你要求的。

這隻適用於$goodHours排序,如果不是,您可以使用asort()函數進行排序。

相關問題