PHP: bir Array Sonraki Uygun Değer, olmayan bir endeksli değeri ile başlayan

5 Cevap php

Şimdi yaklaşık bir gün için bu PHP konuda şaşkına oldum. Temelde, biz 24 saat biçiminde biçimlendirilmiş saatlik bir dizi, ve keyfi bir değer ($hour) (ayrıca 24 saat) var. Sorun biz hemen ilerler değeri ile başlayan, $hour almak, ve dizideki bir sonraki kullanılabilir değerini almak gerekir, bir $hour.

Dizi gibi görünebilir:

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

Ardından saat değeri olabilir:

$hour = 14;

Yani, biz 19 sonraki en iyi zaman olduğunu bilmek için bir yol gerekir. Ayrıca, biz de (vb), ikinci, üçüncü veya dördüncü kullanılabilir değerini almak gerekebilir.

Sorun 14 dizide bir değeri olmadığından, bu bize bir sonraki değere artırmak izin istiyorum başvuru endeksi olmadığını görünüyor.

Basit şeyler yapmak için, ben $goodHours alınır ve değerleri birkaç kez tekrarlanır sadece bu yüzden geri başlangıç ​​yapmak için (belki değil en iyi yolu gidiş ile uğraşmak zorunda değilsiniz, ama hızlı ettik ) düzeltin.

Ben bu Kaçırdığım bir şey basit bir his var, ama herkes bir ışık tutabileceğini eğer ben çok minnettar olacaktır.

Erik

5 Cevap

Eğer aradığınız birden fazla olduğu ilk bulana kadar, dizi üzerinde yineleme için döngü için kullanabilirsiniz:

$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;
    }   
}

Size vermek istiyorum:

5 => 19



Ve, sizin için arıyorlardı öğeyi almak için, ve ondan sonra bazı, bu gibi bir şey kullanabilirsiniz:

$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 />";
    }
}

Size aşağıdaki çıktıyı verecek olan:

5 => 19
6 => 20


Basically, here, the idea is to :

  • advance in the array, until you find the first item that is >= to what you are looking for
    • bulduğunda o ilk döngü, çıkmak
  • If a matching item was found
    • dizi üzerinde döngü, onun ya sonuna kadar,
    • Aradığınız ya gibi birçok ürün bulunamadı ettik.

Ayrıca SPL FilterIterator kullanabilirsiniz. Bu isimli orada hızlı çözüm değil ama, bu, bir yerde / her yerde yineleyici "hazırlamak" ve ardından yineleyici iç nasıl çalıştığını bilmek zorunda olmayan bir işlev / yöntem geçebilir avantajı yani var tamamen farklı bir yineleyici bir sonraki vakit geçirebiliriz.

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);

baskılar

19
20
21

$goodHours zaten sıralanır gibi, o kadar kolay bir şey:

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

Bu dört-liner sonra (yani doğal çizgiler daha az sayıda yazılmış olabilir), $next ya 0 $hour $goodHours olarak uyumlu olamazdı eğer ya da hemen devam değerini içerir $hour. Bu sizin için ne istedi olduğunu.

$goodHours o değil durumda, asort() işlevini kullanarak sıralamak, sıralanabilir olduğunda bu sadece çalışır.

Bu fonksiyonu deneyin:

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

Burada de-facto ilki geçmiş n'th madde alır isteğe bağlı bir "offset" parametresi, dahil bu geri kalanı için benzer bir cevap var.

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