2010-03-26 11 views
5

Sono stato perplesso su questo tema PHP per circa un giorno all'altro. Fondamentalmente, abbiamo una serie di ore formattate in formato 24 ore e un valore arbitrario ($hour) (anche 24 ore). Il problema è che dobbiamo prendere $hour e ottenere il prossimo valore disponibile nell'array, iniziando dal valore che procede immediatamente $hour.PHP: Avanti Disponibile valore in un array, a partire da un valore indicizzato non

La matrice potrebbe essere simile:

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

Allora potrebbe essere il valore delle ore:

$hour = 14; 

Quindi, abbiamo bisogno di qualche modo per sapere che il 19 è il momento migliore successivo. Inoltre, potrebbe anche essere necessario ottenere il secondo, terzo o quarto valore (ecc.) Disponibile.

Il problema sembra essere che, poiché 14 non è un valore nella matrice, non c'è indice di riferimento che farci viene incrementato al valore successivo.

Per semplificare le cose, ho preso lo $goodHours e ho ripetuto più volte i valori solo per non dover tornare indietro all'inizio (forse non è il modo migliore per farlo, ma una soluzione rapida) .

Ho la sensazione che questo è qualcosa di semplice che mi manca, ma mi sarebbe così riconoscente se qualcuno potesse fare una certa luce.

Erik

risposta

4

Si potrebbe utilizzare un ciclo for per iterare l'array, fino a trovare il primo che è più grande di quello che si sta cercando:

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

darebbe:

5 => 19 



E, per ottenere l'oggetto che cercavi, e un po 'dopo che uno, si potrebbe usare qualcosa di simile:

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

che darebbe il seguente output:

5 => 19 
6 => 20 


Fondamentalmente, ecco l'idea:

  • avanzare nell'array, fino a trovare il primo elemento che è >= a quello che stai cercando
    • uscire da quel primo ciclo, quando ha trovato
  • Se un elemento di corrispondenza è stata trovata
    • loop all'interno di una matrice, fino a quando la sua fine,
    • o hai trovato tutti gli oggetti che stavi cercando.
+0

Lo farò uno scatto. Grazie mille per la rapida risposta :) –

+0

Prego :-) Buon divertimento! –

0

Prova questa funzione:

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

È inoltre possibile utilizzare il SPL FilterIterator. Anche se non è la soluzione più veloce, ha il vantaggio di poter "preparare" l'iteratore da qualche parte/ovunque e poi passarlo a una funzione/metodo che non deve sapere come funziona l'iteratore all'interno, cioè tu potrebbe passare un iteratore completamente diverso la volta successiva.

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

stampe

19 
20 
21 
0

Ecco una risposta simile al resto di questi, tra cui un parametro opzionale "offset", che ottiene il vostro articolo n'th oltre la prima de facto.

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

Come $goodHours è già ordinato, che è qualcosa di facile:

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

Dopo che quattro-liner (che può essere scritto in un numero minore di linee naturalmente), $next è o 0 se $hour potessi non essere abbinato in $goodHours o contiene il valore che procede immediatamente $hour. Questo è quello che hai chiesto.

Questo funziona solo se è stato ordinato $goodHours, nel caso in cui non lo fosse, è possibile ordinarlo utilizzando la funzione asort().

Problemi correlati