Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [php]Usuwanie pierwszego elementu tablicy?, jednak array_shift() rozburza mi klucze
kukix
post 6.07.2012, 13:36:30
Post #1





Grupa: Zarejestrowani
Postów: 600
Pomógł: 2
Dołączył: 1.09.2002
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Witam.

Mam tablice generowaną automatycznie, jednak potrzebuje, żeby nie miała ona więcej niż 5 elementów.

Podczas dodawania elementu do tablicy sprawdzam, czy ma powyżej 5 elementów i jeżeli ma to kasuje je funkcją array_shift();

Po ciężkiej walce okazało się, że array_shift() modyfikuje mi klucze pozostałych tablic...

W jaki sposób mogę kontrolować czy tablica ma 5 elementów.. i kasować najstarszy?
Myślałem o pętli foreach(), ale może jest jakis wbudowany w php mechanizm?
Go to the top of the page
+Quote Post
redeemer
post 6.07.2012, 13:49:19
Post #2





Grupa: Zarejestrowani
Postów: 915
Pomógł: 210
Dołączył: 8.09.2009
Skąd: Tomaszów Lubelski/Wrocław

Ostrzeżenie: (0%)
-----


Cytat(kukix @ 6.07.2012, 14:36:30 ) *
Po ciężkiej walce okazało się, że array_shift() modyfikuje mi klucze pozostałych tablic...
Tego nie do końca rozumiem, ale może coś takiego Ci pomoże:
  1. reset($array);
  2. $key = key($array);
  3. unset($array[$key]);


--------------------
Go to the top of the page
+Quote Post
thek
post 6.07.2012, 13:51:08
Post #3





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Wyciągnij 4 elementy, z pominięciem pierwszego używając array_slice i zachowując klucze, czyli z wykorzystaniem WSZYSTKICH parametrów tej funkcji smile.gif
Tylko użyć count, który sprawdza czy tablica ma więcej niż 5 elementów i jeśli tak, to robi array_slice według tego co powżej i dokłada nowy element tablicy smile.gif

EDIT: @up... za dużo zachodu, to co pokazałeś to: resetuje wskaźnik tablicy, czyli ustawia na pierwszym, potem sprawdza nazwę klucza i na koniec robi usunięcie elementu tablicy o takim kluczu. Za dużo motania.
Powód edycji: [thek]: Wytłumaczenie koledze co robi jego kod ;)


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
kukix
post 6.07.2012, 13:54:27
Post #4





Grupa: Zarejestrowani
Postów: 600
Pomógł: 2
Dołączył: 1.09.2002
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Cytat(redeemer @ 6.07.2012, 14:49:19 ) *
Tego nie do końca rozumiem, ale może coś takiego Ci pomoże:



Array_shift() kasuje pierwszy element tablicy, ale modyfikuje klucze tablic tak, żeby zaczynały się od 0.. co powoduje rozsypanie całego skryptu..

Cytat(redeemer @ 6.07.2012, 14:49:19 ) *
reset($array);
$key = key($array);
unset($array[$key]);


musze to wypróbować..

Go to the top of the page
+Quote Post
redeemer
post 6.07.2012, 14:07:48
Post #5





Grupa: Zarejestrowani
Postów: 915
Pomógł: 210
Dołączył: 8.09.2009
Skąd: Tomaszów Lubelski/Wrocław

Ostrzeżenie: (0%)
-----


Cytat(thek @ 6.07.2012, 14:51:08 ) *
EDIT: @up... za dużo zachodu, to co pokazałeś to: resetuje wskaźnik tablicy, czyli ustawia na pierwszym, potem sprawdza nazwę klucza i na koniec robi usunięcie elementu tablicy o takim kluczu. Za dużo motania.
Myślisz, że bym wklejał kod, który nie wiem co robi? smile.gif Można zawsze te 3 linijki wpakować w funkcję. Normalnie pokusiłbym się o zrobienie testów wydajnościowych tych dwóch rozwiązań, ale jest za gorąco, żebym się tym przejmował smile.gif


--------------------
Go to the top of the page
+Quote Post
thek
post 6.07.2012, 14:39:56
Post #6





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Na szybko:
  1. <ul>
  2. <?php
  3. $temp = array('a' => 'gs', 'b' => 'ddr', 'c' => 'sdfsf');
  4. $time_start = microtime(true);
  5. for($i = 0; $i < 100000; $i++)
  6. {
  7. if(count($temp) > 4)
  8. {
  9. reset($temp);
  10. $key = key($temp);
  11. unset($temp[$key]);
  12. }
  13. $temp[$i] = 'ggsggstr';
  14. }
  15. $time_end = microtime(true);
  16. ?>
  17. <li>100k razy z resetem = <?php echo ($time_end - $time_start).' -> '.print_r($temp, TRUE); ?></li>
  18. <?php
  19. $temp = array('a' => 'gs', 'b' => 'ddr', 'c' => 'sdfsf');
  20. $time_start = microtime(true);
  21. for($i = 0; $i < 100000; $i++)
  22. {
  23. if(count($temp) > 4)
  24. {
  25. $temp = array_slice($temp, 1, 4, TRUE);
  26. }
  27. $temp[$i] = 'ggsggstr';
  28. }
  29. $time_end = microtime(true);
  30. ?>
  31. <li>100k razy z array_slice = <?php echo ($time_end - $time_start).' -> '.print_r($temp, TRUE); ?></li>
  32. </ul>

Z wynikiem:
Kod
100k razy z resetem = 2.9823479652405 -> Array ( [99995] => ggsggstr [99996] => ggsggstr [99997] => ggsggstr [99998] => ggsggstr [99999] => ggsggstr )
100k razy z array_slice = 2.085914850235 -> Array ( [99995] => ggsggstr [99996] => ggsggstr [99997] => ggsggstr [99998] => ggsggstr [99999] => ggsggstr )

Jak widać array_slice jest około 30% szybsze rozwiązanie i na pewno daje identyczny wynik w obu wypadkach, co widać po indeksach.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
redeemer
post 6.07.2012, 15:03:00
Post #7





Grupa: Zarejestrowani
Postów: 915
Pomógł: 210
Dołączył: 8.09.2009
Skąd: Tomaszów Lubelski/Wrocław

Ostrzeżenie: (0%)
-----


Dzieki za kod smile.gif U mnie na PHP 5.3.3-7+squeeze13 with Suhosin-Patch i Intel® Core™ i7 CPU 920 @ 2.67GHz wyniki są porównywalne (~0.001s czasu różnicy z przewagą raz na jedną a raz na drugą szalę). Co ciekawe, gdy limit na ilość elementów w tablicy się zwiększa, rozwiązanie z resetem praktycznie nie zmienia czasu wykonania, zaś w rozwiązaniu z array_slice rośnie.


--------------------
Go to the top of the page
+Quote Post
thek
post 6.07.2012, 16:35:56
Post #8





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




To normalne zachowanie z limitem. Unset dostaje bowiem konkretny, jeden, klucz i go usuwa. Koszt resetowania, pobierania pierwszego klucza i usuwania jest w miarę wysoki, ale zawsze tak samo przebiega, stąd długość tablicy nie ma dla niego znaczenia. Zawsze wytnie pierwszy i koniec.

Z kolei im większy offset i długość wycinanego kawałka, tym dłużej array_slice przechodzi po kluczach kolejnych i czas mu rośnie.
Całość jednak nieco inaczej by wyglądała, gdyby tablica wejściowa na wstępie była dowolnej długości i już na wstępie mogła mieć zarówno 1 jak i 40 elementów. O ile samo działanie nadal byłoby identycznie szybkie, o tyle doszła by Ci bowiem wstępna obróbka dla kodu z resetem jako "inicjalizacja", tak, by usunąć tyle elementów z przodu, by Ci zostało góra 4 elementy. Array_slice wystarczy leciutko jedynie zmodyfikować. Zamiast
  1. $temp = array_slice($temp, 1, 4, TRUE);

wstawia się bowiem
  1. $temp = array_slice($temp, -4, 4, TRUE);

co zawsze wycina maksymalnie 4 ostatnie elementy tablicy. Oczywiście nadal koszt się zwiększa z wycinanym kawałkiem, ale przestajesz się martwić czy dostarczona tablica jest pusta, ma 2 czy 5000 elementów.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
redeemer
post 7.07.2012, 09:37:48
Post #9





Grupa: Zarejestrowani
Postów: 915
Pomógł: 210
Dołączył: 8.09.2009
Skąd: Tomaszów Lubelski/Wrocław

Ostrzeżenie: (0%)
-----


Dodam jeszcze, że array_slice zwraca tablicę, którą wcześniej musi zainicjować i przekopiować do niej dane. Więc ogólna złożoność obliczeniowa wychodzi lepiej na korzyść rozwiązania z resetem, ale to już offtop smile.gif


--------------------
Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 21.07.2025 - 07:26