Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [SPL] tworzenie iteratora, w miejsce 2 pętli jedna w drugiej
DeyV
post
Post #1





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




Odkąd poznałem możliwości SPL jestem pod dużym wrażeniem możliwości podsuwanych tam pomysłow, i coraz częściej staram się z nich korzystać.

Zacząłem stosować iteratory, i rzeczywiście - okazały się w wielu przypadkach bardzo przydatne, zmiejszając ilość (chyba (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg) ) pamięci, którą musi zaalokować pamięć, i przyspieszając jego działanie w wielu przypadkach (mniejsza ilość pętli)

Zastanawiam się jednak, czy istnieje jakiś prosty sposób na tworzenie iteratoró w nieco bardziej złożonych przypadkach.

Zacznijmy od jakiegoś prostego przypadku. Np. mamy 2 tablice, a potrzebna jest nam jedna, w której znajdują się wszystkie kombinacje elementów z tych 2 powyższych (czyli każdy z każdym).
Normalnie rozwiązanie bardzo proste.
Dwa foreach, jeden drugim, i generowanie tablicy wynikowej.
  1. <?php
  2.  
  3. $aOwoce = array( 'jabłko', 'banan', 'wiśnia' );
  4. $aKolory = array( 'niebieski', 'czerwony' );
  5. $aWynik = array();
  6. foreach( $aOwoce as $sOwoc ){
  7.  foreach( $aKolory as $sKolor ){
  8. $aWynik[] = $sKolor . ' '. $sOwoc ;
  9. }
  10. }
  11. ?>


Jednak w ten sposób przechowujemy całą tą tablicę zupełnie niepotrzebnie, bo tak naprawdę do dalszego działania programu będziemy potrzebowali 1, kolejny jej element w danym momencie....
Oczywiście - nawet na chłopski rozum można napisać odpowiedni iterator, wymaga jednak całkiem złożonego algorytmu sprawdzania kolejnych elementów i ich zwracania.
A problem wydaje mi się na tyle standardowy, że powinny być jakieś "standardowe" rozwiązania - chyba że mam po prostu zaćmę i czegoś oczywistego nie udało mi sie dotychczas zauważyć... (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

// ps. i nie próbujcie mi odpowiedzieć, że są jakieś standardowe funkcje do łączenia tablic, bo normalnie ... zamorduję (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif)
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
DeyV
post
Post #2





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




oczywiście, hawk.
Mimo to miałem nadzieję, że żucicsz jakimś ciekawym linkiem o tej tematyce.
Ale fakt - faktem. Po napisaniu nie wygląda to już nawet tak groźnie, i choć ciągle się zastanawiam, czy napisane jest optymalnie (jakoś dużo tych warunków mi się zrobiło :/ ) to jednak działa w pełni zgodnie z założeniami.

Dla wątpiących: (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)

  1. <?php
  2.  
  3. /**
  4.  * @date 9.02.2005
  5.  */
  6. class GenerateNames implements Iterator
  7. {
  8.  
  9. private $aFirst, $aSecond = array();
  10. private $iFirstCount, $iSecondCout = 0;
  11. private $iFirstIt, $iSecondIt = 0;
  12.  
  13.  
  14. function __construct( $aFirst, $aSecond ){
  15. $this->aFirst = $aFirst;
  16. $this->aSecond = $aSecond;
  17.  
  18. $this->iFirstCount = count( $this->aFirst );
  19. $this->iSecondCout = count( $this->aSecond );
  20.  
  21. }
  22.  
  23. /** Rewind the Iterator to the first element.
  24.  */
  25. function rewind() {
  26. $this->iFirstIt = $this->iSecondIt = 0;
  27. }
  28.  
  29. /** Return the current element.
  30.  */
  31. function current() {
  32. return $this->aFirst[ $this->iFirstIt ] .' '. $this->aSecond[ $this->iSecondIt ];
  33. }
  34.  
  35. /** Return the key of the current element.
  36.  */
  37. function key() {
  38. return $this->iFirstIt .'-'. $this->iSecondIt;
  39. }
  40.  
  41. /** Move forward to next element.
  42.  */
  43. function next(){
  44. if( $this->iSecondIt < $this->iSecondCout -) {
  45. ++$this->iSecondIt;
  46. }
  47. else{
  48. $this->iSecondIt = 0;
  49. ++$this->iFirstIt;
  50. }
  51. }
  52.  
  53. /** sprawdza czy nie przekroczyliśmy jeszcze zakresu
  54.  * @return bool
  55.  */
  56. function valid() {
  57. return $this->iFirstCount > $this->iFirstIt && $this->iSecondCout > $this->iSecondIt ;
  58. }
  59. }
  60.  
  61.  
  62. $Element = new GenerateNames( 
  63. array( 'jabłko', 'wiśnia', 'banan' ),
  64. array( 'czerwone', 'bordowa', 'żółty' ) );
  65.  
  66. foreach( $Element as $iKey => $sWord ) {
  67. echo $iKey . ' => ' . $sWord . '<br />';
  68. }
  69.  
  70.  
  71. ?>


mile widziane oczywiście propozycje poprawy tego kodu...

//ps. a jeśli ktoś się zastanawia, czy jest sens tworzenia taiej ilości kodu, zamiast zaprezentowanych powyżej dwóch pętli - niech wyobrazi sobie, że ten iterator nie pracuje na 2 tylko na np. 4 tablicach. I policzy - jakiej wielkości byłaby tablica wynikowa....
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 19.09.2025 - 17:50