Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Porównanie tablic
Forum PHP.pl > Forum > PHP
styryl
Mam 2 tablice:

1.

  1. (
  2. [0] => Array
  3. (
  4. [Knt_Telefon1] => 322035105
  5. [Knt_Telefon2] =>
  6. )
  7.  
  8. [1] => Array
  9. (
  10. [Knt_Telefon1] => 322065105
  11. [Knt_Telefon2] => 322065115
  12. )
  13.  
  14. [2] => Array
  15. (
  16. [Knt_Telefon1] => 322289156
  17. [Knt_Telefon2] =>
  18. )
  19.  
  20. [3] => Array
  21. (
  22. [Knt_Telefon1] => 322033117
  23. [Knt_Telefon2] => 322012105
  24. )
  25. )
  26.  


2.

  1. (
  2. [0] => Array
  3. (
  4. [nr] => 322065105
  5. )
  6.  
  7. [1] => Array
  8. (
  9. [nr] => 322289156
  10. )
  11.  
  12. [2] => Array
  13. (
  14. [nr] => 322033117
  15. )
  16.  
  17. [3] => Array
  18. (
  19. [nr] => 322562336
  20. )
  21.  
  22. [4] => Array
  23. (
  24. [nr] => 322503669
  25. )
  26. )
  27.  


Chce porównać obie tablice tak aby zwróciło wszystkie numery z tablicy 1 których nie ma w tablicy 2.

Próbowałem z array_diff_assoc ale nie działa. Robiłem też w pętli foreach ale skrypt przerywa działanie i nie wywala żadnego błędu. I co najważniejsze w tablicy nr 1 jest ponad 80 000 kluczy (razy 2 [Knt_Telefon1] i [Knt_Telefon2]) oraz w tablicy nr 2 jest około 70 000 rekordów.

Da się to jakoś optymalnie rozegrać?
CuteOne
1. Wygeneruj sobie druga tablicę tak aby wyglądała w ten sposób:

  1. (
  2. [0] => 322065105
  3. [1] => 322289156
  4. //itd
  5. )


  1. foreach($tablica1 as $k => $v) {
  2.  
  3. if(!in_array($v['Knt_Telefon1'], $tablica2)
  4. && !in_array($v['Knt_Telefon2'], $tablica2)) {
  5.  
  6. $newArray[] = $v;
  7. }
  8. }
Sephirus
Jeżeli robisz to jednorazowo to nie ma co za bardzo kombinowac z optymalnością. Sugeruje dać set_time_limit na duży i większy przydział pamięci jeżeli jest potrzebny wink.gif

Co do kodu spróbuj po prostu:

  1. $tab1in; // TAB 1
  2. $tab2in; // TAB 2
  3. $tab1 = array();
  4. $tab2 = array();
  5. $tab3 = array(); // TAB w której będą numery z tab1in ktorych nie ma w tab2in
  6.  
  7. // Konwertujemy tabele (tak będzie łatwiej)
  8.  
  9. foreach($tab1in AS $nr)
  10. {
  11. $tab1[] = $nr['Knt_Telefon1'];
  12. $tab1[] = $nr['Knt_Telefon2'];
  13. }
  14.  
  15. foreach($tab2in AS $nr)
  16. {
  17. $tab2[] = $nr['nr'];
  18. }
  19.  
  20.  
  21. foreach($tab1 AS $t1)
  22. {
  23. if(!in_array($t1,$tab2)) $tab3[] = $t1;
  24. }
  25.  
  26.  


Proste, chwilę potrwa ale powinno działać

HTH! wink.gif
styryl
Dzięki wielkie, @ephirus - próbowałem w podobny sposób jednak nagle po sprawdzeniu około 30-35 tyś kluczy przestawało działać (zero błędu przy czym limity czasowe i pamięciowe ściągnięte). Puściłem kod CuteOne i się póki co mieli.
Co do częstotliwości to mniej więcej musi chodzić co tydzień.
Sephirus
To takie dodatkowe info - żeby wiedzieć co się dzieje w danej chwili zawsze możesz co jakiś czas (co ileś operacji sprawdzania) dać loga. To znaczy nadpisać plik z info, ile rekordów przemieliło itd... Wtedy jak coś się skrzaczy masz info kiedy i jak dobrze to napiszesz także "dlaczego" wink.gif Ja tak kiedyś skasowałem sporą bazę bo mi się jedna literka pomyliła ;P (backup był) tongue.gif

P.S. Pamiętam też, że w zależności od ustawień serwera może nie działać ustalanie czasu trwania skryptu - serwer ustawia to wedlug siebie - spotkałem się z tym w Nginx na przykład - więc jak nic nie pomoże to sprawdź też czy Ci po prostu serwer na "chama" skryptu nie killuje wink.gif
Noidea
Wyszukiwanie różnic w dwóch tablicach po ~100 000 elementów nie powinno trwać aż tak długo, żeby można było powiedzieć "póki co się mieli". Żeby przyspieszyć działanie takiego skryptu trzeba zastosować hashtablice (wyszukiwanie elementów w hashtablicy jest znacznie szybsze, niż porównywanie po kolei n elementów zwykłej tablicy). Jako że w PHP tablice asocjacyjne mogą być traktowane jako hashtablice, to kod jest bardzo prosty. W praktyce sprowadza się do tego, co pokazali CuteOne i Sephirus, tyle że klucze tablic zamienione są z wartościami:
  1. <pre>
  2. <?php
  3.  
  4. $startTime = microtime( true );
  5.  
  6. // Wczytujemy drugą tablicę i zamieniamy jej format z:
  7. // array (
  8. // array( "nr" => 1234 ),
  9. // array( "nr" => 2345 ),
  10. // array( "nr" => 9876 ),
  11. // ...
  12. // );
  13. //
  14. // na:
  15. // array (
  16. // 1234 => 1,
  17. // 2345 => 1,
  18. // 9876 => 1,
  19. // ...
  20. // );
  21. include "arr2.php";
  22.  
  23. $telArray = array();
  24. foreach( $arr2 as $item )
  25. {
  26. $telArray[$item["nr"]] = 1;
  27. }
  28.  
  29.  
  30. // Wczytujemy pierwszą tablicę i sprawdzamy każdy jej
  31. // numer telefonu z drugą tablicą. Jeśli NIE znajduje
  32. // się w drugiej tablicy dodajemy taki numer do
  33. // wynikowej tablicy $diffTelArray
  34. include "arr1.php";
  35.  
  36. $diffTelArray = array();
  37. foreach( $arr1 as $item )
  38. {
  39. $tel1 = $item["Knt_Telefon1"];
  40. $tel2 = $item["Knt_Telefon2"];
  41.  
  42. if( !empty( $tel1 ) && !isset( $telArray[$tel1] ) )
  43. {
  44. $diffTelArray[$tel1] = 1;
  45. }
  46. if( !empty( $tel2 ) && !isset( $telArray[$tel2] ) )
  47. {
  48. $diffTelArray[$tel2] = 1;
  49. }
  50. }
  51.  
  52. // Jako że wynikowa tablica również ma format:
  53. // numer_telefonu => 1
  54. // "poprawiamy" ją funkcją array_keys
  55. $diffTelArray = array_keys( $diffTelArray );
  56.  
  57.  
  58. echo "Time: " . round( microtime( true ) - $startTime, 3 ) . " s\n";
  59. echo "Peak memory: " . number_format( memory_get_peak_usage() / 1024 / 1024, 2, ".", " " ) . " MB\n\n";
  60.  
  61. ?>
  62. </pre>


Wygenerowałem sobie tablice 1 i 2 zawierające odpowiednio 70 000 i 80 000 elementów (za telefony przyjąłem wartości losowe z zakresu 320000000 - 329999999) i powyższy kod wykonuje się u mnie w 0.75 sekundy i zajmuje w szczytowym momencie niecałe 80MB pamięci.


PS. Jeśli ma się to wykonywać raz, lub raz na tydzień jakoś w nocy, to faktycznie nie trzeba się przejmować wydajnością. W przeciwnym wypadku warto się nad tym zastanowić, bo wzrost wydajności jest znaczny.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.