2013-01-22 13 views
14

Używam frameworka PHP, który zwraca wyniki SQL jako obiekty iterowalne. Problem polega na tym, że mam kwerendę SQL, która zwraca jeden wiersz i nie chcę tworzyć foreach, aby uzyskać pierwszy i jedyny element.Jak uzyskać dostęp do pierwszego elementu w iteratorze?

Jak to zrobić?

te nie działają:

$obj->item(0)->propName; 
$obj->next()->propName; 
$obj[0]->propName; 

pomysłów?

+3

'$ obj-> current() -> propName' może? – Crisp

+2

wstaw 'var_dump' i sprawdź strukturę obiektu wynikowego –

+0

Odpowiedź Crispa rozwiązała problem. Stwórz odpowiedź sep i zaznaczę ją jako odpowiedź. var_dump dał mi bezużyteczne śmieci takie jak to: http://pastebin.com/GeNDbiN4 – neubert

Odpowiedz

13

Zakładając przez „iterable”, to znaczy, że obiekt implementuje Iterator interface, można użyć $obj->current() aby pobrać bieżący element, więc $obj->current()->propName jest chyba to, co chcesz.

Jeśli wskaźnik iterator został przeniesiony (na przykład, jeśli został użyty w foreach, która nie zresetować wskaźnik), a następnie można nazwać $obj->rewind() ustawić kursor z powrotem do pierwszego elementu przed wywołaniem $obj->current() .

6

Istnieją tylko dwainterfejsy klasy, który może być wykonywany: Iterator i IteratorAggregate (każdy inny musi implementować jeden z nich).


Iterator

Pierwszy element Iterator można uzyskać w następujący sposób:

$iterator->rewind(); 
if (!$iterator->valid()) { 
    throw new Exception('There is no any element!'); 
} 
$firstElement = $iterator->current(); 

Jeżeli jesteś pewien:

  • $iterator nigdy nie został poprzecinany foreach lub jeśli tak, ale pętla nigdy nie została zatrzymana z break;
  • nigdy nie nazwano $iterator->next();

można pominąć $iterator->rewind(); z poprzedniego przykładu.

Jeżeli jesteś pewien, że liczba elementów w $iterator jest nie zero, można nawet pominąć bloku testowanie stanu $iterator->valid().

Więc jeśli te wcześniejsze warunki są zachowane, to co trzeba to po prostu:

$firstElement = $iterator->current(); 

IteratorAggregate

Nie można uzyskać pierwszy element dowolny po prostu. IteratorAggergate jest właściwie tylko kopertą dla Iteratora lub innego IteratorAggregate. Logicznie oznacza to, że na końcu znajduje się Iterator. Niestety nie wiesz, ile poziomów jest głębokich.

Najprostszym sposobem na osiągnięcie pierwszego elementu jest:

$array = iterator_to_array($iteratorAggregate); 
if (count($array) === 0) { 
    throw new Exception('There is no any element!'); 
} 
$firstElement = reset($array); 

(! I zaskakująco dokładnie to samo rozwiązanie działa również na Iterator)

Jesteśmy przekształcenie go do zwykłej tablicy więc następna procedura to usual way to fetch the first element from an array. Niestety w przypadku tablicy biigowej jest to trochę przesada, ponieważ kopia wszystkich elementów musi zostać utworzona, mimo że potrzebujemy tylko jednego.

Jest jedno rozwiązanie, które wydaje się niedbały:

while ($iteratorAggregate instanceof \IteratorAggregate) { 
    $iteratorAggregate = $iteratorAggregate->getIterator(); 
} 
$iterator = $iteratorAggregate; 

aw następnym kroku będziemy pracować z nim, jakby to było iterację w pierwszym przykładzie. Zrobiłem prosty test porównawczy dla tablicy liczącej 10000 członków, a to rozwiązanie było prawie 6 razy szybsze.

LLAP

Powiązane problemy