Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Duplikaty w tablicy - jak usunąć?
Forum PHP.pl > Forum > PHP
miki_kol
Witam
Wiem że o duplikatach była tu już mowa jednak nie znalazłem odpowiedzi na mój problem, a przedstawione tu rozwiązania ni zadziałały mi.

Importuję dane z pliku do dwóch tablic i łączę je w trzeciej ... wspólnej w odpowiedniej konfiguracji. Jednak w tej chwili przy 4 rekordach zdarzają się duplikaty typu:

  1. Id_wynik | Wartość_lewa | Wartość_prawa
  2. 1 | aaa | xxx
  3. 2 | aaa | yyy
  4. 3 | xxx | aaa
  5. ....


gdzie rekord 1 i 3 są takie same tylko odwrócone. Jest to co prawda poprawne ale nie pożądane i chciałbym by się nie pojawiło. Tym bardziej że dwie pierwsze tabele będą zawierały czasem nawet po kilkadziesiąt rekordów. czyli szukanie takich duplikatów będzie raczej ciężkie.

Gdyby ktoś miał jakiś pomysł ... byłbym wdzięczny

darko
array_unique
miki_kol
Hmm ... myślę że było by to za proste. Dla pewności jeszcze przetestowałem ale to nie zadziałało.

myślę że logicznie patrząc na to oba rekordy są różne. W tej chwili to są dwie kolumny z tymi samymi danymi na przemian ale robiąc z tego jedną kolumnę ... to aaaxxx i xxxaaa to dwie zupełnie różne wartości. myślę że dlatego array_unique nie rozpoznaje tego i dlatego mam z tym problem.

Myślałem też by zrobić kopię tablicy zamienić kolumny miejscami i porównać je przez array_search ... wyeliminować wspólne rekordy, ale obawiam się że to usunie mi oby dwie pozycje
darko
Mam taką koncepcję, spróbuj tak: masz 2 osobne tablice $tab1 i $tab2 i teraz:
- scalasz jej tymczasowo w jedną powiedzmy $tab0
- jedziesz w pętli po pierwszej małej tablicy ($tab1), kontrolując wartość indeksu ($i++)
- sprawdzasz w każdej iteracji czy zlepek elementu x tablicy1 i tablicy2 oraz odwrotnie (2 i 1) istnieje w tablicy0:
  1. $tab3 = array(); // tu przechowujemy "unikalne" wartości
  2. for($i=0; $i<count($tab1); $i++) {
  3. if(!in_array($tab1[$i].$tab2[$i], $tab0) && !in_array($tab2[$i].$tab1[$i], $tab0)) {
  4. $tab3[] = $tab1[$i].$tab2[$i];
  5. // czy odwrotnie, jak tam potrzebujesz: $tab3[] = $tab2[$i].$tab1[$i];
  6. }
  7. }
  8. //
  9. // tablica $tab3 powinna zawierać unikatowe wartości pozbawione kombinacji $tab1[$i].$tab2[$i] i odwrotnie. Polecam przepisać to w funkcję i zrobić array_walk
  10. //
kabot
Proponuję najpierw znormalizować dane czyli np. kolumnę lewą i prawą rozpisać tak, aby lewa zawierała alfabetycznie wcześniejszą wartość.
Nie pojawi się wtedy aaaxxx i xxxaaa tylko 2 razy aaaxxx, to które należy usunąć zależy od Ciebie.
miki_kol
darko Twoje rozwiązanie jest ok i nawet o tym pomyślałem ale jest jedna zła rzecz w tym rozwiązaniu ... wywala mi tu obydwa kombinacje a chodzi mi o wywalenie tylko jednej kombinacji (dowolnej).

kabot dane pochodzą z 2 różnych tabel i łączą się w 3 wspólnej w 2 kolumnach. Jak dokonać zamiany wpisów w dokładnie tym jednym rekordzie. Poza tym tak jak wcześniej mówiłem będą przypadki że tabele 1 i 2 będą się składały z kilkudziesięciu wierszy co po dokonaniu kilku kombinacji da w tabeli 3 ponad setke kombinacji. Jak miałbym wtedy trafić w konkretne rekordy?
darko
Pokaż wszystkie trzy tablice: dwie małe i jedną będącą połączeniem tych dwóch małych. Pokaż też swój kod, jak łączysz te dwie do jednej itd. Coś mi się wydaje, że sprawa jest bardziej prosta niż się wydaje...

// edit
nie wiem czy nie przekombinuję, ale sprawdź co da zamiana && na xor
Pilsener
Cytat
Importuję dane z pliku do dwóch tablic i łączę je w trzeciej ... wspólnej w odpowiedniej konfiguracji
- problem stary jak świat, bo np. jeden przedstawi się PESELem, inny REGONem, trzeci NIPem etc. Metodologia postępowania jest taka:

1. Decydujemy jakie warunki musi spełniać rekord, by był uznany za duplikat (np. identyczne nazwisko i imię jeszcze nie, ale imię + nazwisko + numer telefonu już tak)

2. Tworzymy odpowiednie pole, gdzie generujemy unikatowy klucz:
  1. $token = md5($pole1.$pole2.$pole3);
- u Ciebie będzie to trochę bardziej skomplikowane, bo np. Jan Karol i Karol Jan to będą identyczne rekordy smile.gif Wystarczy posortować kolejność warunków do klucza:
  1. $warunki[1] = 'Jan';
  2. $warunki[2] = 'Karol';
  3. sort($warunki);
  4. $token = md5(join("",$warunki));
- wtedy niezależnie od tego, czy "Jan" będzie 1 czy 2, wygenerowany klucz będzie identyczny

3. I teraz mamy już prosto:
- jeśli używamy bazy to wystarczy dodać pole "token" i nałożyć indeks unique - duplikaty zostaną odrzucone
- jeśli pliku/tablicy to też nie jest trudno - konstrujemy tablicę tak, aby jej kluczem był nasz token:
  1. $tablica[$token] = $reszta;
- oczywiste, że nie mogą istnieć dwa elementy o identycznym kluczu, więc będzie tylko jeden Jan Karol czy też Karol Jan smile.gif
miki_kol
A jednak nie działa sad.gif

Dziękuję bardzo za pomoc ... ale już działa smile.gif
Dzięki darko za naprowadzenie mnie na odpowiedni tok myślenia smile.gif Wystarczyło Twój kod zmodyfikować.
  1. $tab3 = array(); // tu przechowujemy "unikalne" warto?ci
  2. for($i=0; $i<count($tab1); $i++) {
  3.  
  4. if(!in_array($tab1[$i].$tab2[$i], $tab0)) { // nie filtrujemy przez obie opcjie tylko przez jedną
  5.  
  6. $tab3[] = $tab1[$i].$tab2[$i];
  7. // czy odwrotnie, jak tam potrzebujesz: $tab3[] = $tab2[$i].$tab1[$i];
  8. }
  9. }
  10. //
  11. // tablica $tab3 powinna zawierać unikatowe warto?ci pozbawione kombinacji $tab1[$i].$tab2[$i] i odwrotnie. Polecam przepisać to w funkcję i zrobić array_walk
  12. //


i teraz zmieniając kolejność kolumn w zapytaniu IF otrzymuję albo pierwszy albo drugi wpis ... mogę wybierać.

Myślę że spokojnie należy ci się POMÓGŁ. Jeszcze raz dzięki. Dla mnie temat do zamknięcia.

*******************************************************
*******************************************************
Wracam niestety do tematu sad.gif ponieważ to jednak nie działa
Co prawda post będzie obszerny ale postaram się przedstawić co ma wykonać kod. Otóż chcę zrobić programik który ma na celu zamianę listy połączeń elektrycznych wykonanej w excelu w listę punkt-punkt do programu testera.

Oto jak wygląda schemat

i może jeszcze jak mogą wyglądać inne schematy ponieważ ten nad którym pracuję teraz jest jednym z prostszych.

tabela w excelu to:

KOSC1 PIN1 KOSC2 PIN2 PRZEWÓD
X57 Klip 1 22:03
X44:2 1 Klip 1 22:01
X44:1 1 Klip 1 22:02
X44:1 2 X44:2 2 40:01


Wynik z całości powinien wyjść taki :
X44:1/2 - X44:2/2
X44:1/1 - X57
X44:1/1 - X44:2/1
X44:2/1 - X57

Czyli jak widać wszystkie możliwe kombinacje bez powtórzeń gdzie pominięty jest element o nazwie Klip1 (tak jakby w to miejsce włożyć poszczególne piny)

teraz czas na kody:

Ładuję dane z pliku:
  1. if (move_uploaded_file($_FILES['userfile']['tmp_name'], $location))
  2. {
  3. $plik = "test/test.txt";
  4. $dane_plk = file($plik);
  5. for($i=0;$i<count($dane_plk);$i++)
  6. {
  7. $split = explode(" ", $dane_plk[$i]);
  8.  
  9. $ladowanie['kosc_1'][] = $split[0];
  10. $ladowanie['kontakt_1'][] = $split[1];
  11. $ladowanie['kosc_2'][] = $split[2];
  12. $ladowanie['kontakt_2'][] = $split[3];
  13. $ladowanie['przew'][] = $split[4];
  14. }
  15. echo "Plik został załadowany poprawnie...<br><br>
  16. }
  17. else
  18. {
  19. echo "Plik nie został załadowany...<br><br>";
  20. }




  1. $ile_ladowanie = count($ladowanie['kosc_1']);
  2.  
  3. $gotowa = array('kosc_1' => array(), 'kosc_2' => array(), 'przew_1' => array(), 'przew_2' => array());
  4. $gotowa2 = array('kosc_1' => array(), 'kosc_2' => array(), 'przew_1' => array(), 'przew_2' => array());
  5. $gotowa4 = array('kosc_1' => array(), 'kosc_2' => array(), 'przew_1' => array(), 'przew_2' => array());
  6. $gotowa3 = array();
  7. $przyp_krimp = array('krimp' => array(), 'kosc' => array(), 'przew' => array());
  8.  
  9. for($y=0;$y<$ile_ladowanie;$y++)
  10. {
  11. $lp = $y+1;
  12.  
  13. echo $lp.'. '.$ladowanie['kosc_1'][$y].'/'.$ladowanie['kontakt_1'][$y].' ('.$ladowanie['przew'][$y].') '.$ladowanie['kosc_2'][$y].'/'.$ladowanie['kontakt_2'][$y].'<br>';
  14.  
  15. if(($ladowanie['kosc_1'][$y]!="Klip 1")&&($ladowanie['kosc_2'][$y]!="Klip 1")) // zapisuję już gotowe połączenia czyli te które nie przechodzą przez Klip1
  16. {
  17. $gotowa['kosc_1'][] = $ladowanie['kosc_1'][$y].'/'.$ladowanie['kontakt_1'][$y];
  18. $gotowa['kosc_2'][] = $ladowanie['kosc_2'][$y].'/'.$ladowanie['kontakt_2'][$y];
  19. $gotowa['przew_1'][] = $ladowanie['przew'][$y];
  20. $gotowa['przew_2'][] = $ladowanie['przew'][$y];
  21. }
  22. else
  23. {
  24. if($ladowanie['kosc_1'][$y]=="Klip 1") //przydzielam do klipa po lewej stronie kostkę z prawek
  25. {
  26. $przyp_krimp['krimp'][] = $ladowanie['kosc_1'][$y];
  27. $przyp_krimp['kosc'][] = $ladowanie['kosc_2'][$y].'/'.$ladowanie['kontakt_2'][$y];
  28. $przyp_krimp['przew'][] = $ladowanie['przew'][$y];
  29. }
  30. if($ladowanie['kosc_2'][$y]=="Klip 1") //przydzielam do klipa po prawej stronie kostkę z lewej
  31. {
  32. $przyp_krimp['krimp'][] = $ladowanie['kosc_2'][$y];
  33. $przyp_krimp['kosc'][] = $ladowanie['kosc_1'][$y].'/'.$ladowanie['kontakt_1'][$y];
  34. $przyp_krimp['przew'][] = $ladowanie['przew'][$y];
  35. }
  36. }
  37. }


Wynik to:
pierwsze gotowe wpisy
1. X44:1/2 (40:01) - X44:2/2 (40:01) - jedno poprawne połączenie


--------------------------
gotowe zamienniki klipa
1. Klip 1 - X57/2 (22:03)
2. Klip 1 - X44:2/1 (22:01)
3. Klip 1 - X44:1/1 (22:02)


Wykonuję podmianę Klip 1 na wcześniej przypisane pozycje:

  1. for($c=0;$c<$ile_ladowanie_2;$c++)
  2. {
  3. for($v=0;$v<$ile_krimp_3;$v++)
  4. {
  5. if($ladowanie['kosc_2'][$c]==$przyp_krimp['krimp'][$v])
  6. {
  7. if($ladowanie['kosc_1'][$c].'/'.$ladowanie['kontakt_1'][$c]!=$przyp_krimp['kosc'][$v])
  8. {
  9. echo $ladowanie['kosc_1'][$c].'/'.$ladowanie['kontakt_1'][$c].' ('.$ladowanie['przew'][$c].') - '.$przyp_krimp['kosc'][$v].' ('.$przyp_krimp['przew'][$v].')<br>';
  10.  
  11. $gotowa2['kosc_1'][] = $ladowanie['kosc_1'][$c].'/'.$ladowanie['kontakt_1'][$c].'('.$ladowanie['przew'][$c].')';
  12. $gotowa2['kosc_2'][] = $przyp_krimp['kosc'][$v];
  13.  
  14. $gotowa3[] = $ladowanie['kosc_1'][$c].'/'.$ladowanie['kontakt_1'][$c].$przyp_krimp['kosc'][$v];
  15. }
  16. }
  17. if($ladowanie['kosc_1'][$c]==$przyp_krimp['krimp'][$v])
  18. {
  19. if($ladowanie['kosc_2'][$c].'/'.$ladowanie['kontakt_2'][$c]!=$przyp_krimp['kosc'][$v])
  20. {
  21. echo $ladowanie['kosc_2'][$c].'/'.$ladowanie['kontakt_2'][$c].' ('.$ladowanie['przew'][$c].') - '.$przyp_krimp['kosc'][$v].' ('.$przyp_krimp['przew'][$v].')<br>';
  22.  
  23. $gotowa2['kosc_1'][] = $przyp_krimp['kosc'][$v];
  24. $gotowa2['kosc_2'][] = $ladowanie['kosc_2'][$c].'/'.$ladowanie['kontakt_2'][$c].'('.$ladowanie['przew'][$c].')';
  25.  
  26. $gotowa3[] = $przyp_krimp['kosc'][$v].$ladowanie['kosc_2'][$c].'/'.$ladowanie['kontakt_2'][$c];
  27. }
  28. }
  29. }
  30. }


i tu zaczynają się schody sadsmiley02.gif
Wynik jaki dostaję to :

X57 (22:03) - X44:2/1 (22:01)
X57 (22:03) - X44:1/1 (22:02)
X44:2/1 (22:01) - X57 (22:03)
X44:2/1 (22:01) - X44:1/1 (22:02)
X44:1/1 (22:02) - X57 (22:03)
X44:1/1 (22:02) - X44:2/1 (22:01)

gdzie pogrubione pozycje są poprawne a pozostałe zbędne

Niestety in_array nie działa tu. array_unique tez tu nie pomaga

Ma ktoś może jakiś pomysł jak otrzymać wynik bez powtórzeń?
Pilsener
Przecież napisałem w poście wyżej - masz wygenerować KLUCZ, którego bazą będą pola, które nie mogą się powtarzać, pola te wrzucasz do tablicy, sortujesz (by zapewnić zawsze identyczną kolejność elementów, niezależnie od ich położenia) a utworzony klucz będzie dodatkowym elementem (utworzonym sztucznie), po którym będą odrzucane duplikaty. Algorytm tworzący klucz można zmieniać w zależności od sytuacji.

Ten sam mechanizm możesz wykorzystać w excelu, by dodać dodatkową kolumnę decydującą o tym, czy rekord będzie unikalny czy nie.
miki_kol
hm ... myślałem już o jakichś prefiksach i takich innych ... tamto nie zadziałało

teraz właśnie rozważam twoje Pilsener rozwiązanie i jednej rzeczy nie mogę pojąć (może tępy jestem a może już za długo nad tym siedzę) ... chodzi mi o zmienną $warunki . Ponieważ moje dane są w tablicy asocjacyjnej ... w myśl tego co ty mi mówisz miałbym je przypisać do zwykłej ... (tak zrozumiałem) ... nie rozumiem tylko w jaki sposób. Wygenerowałem klucz md5 dla wszystkich par tylko do czego to porównać ponieważ teraz wszystkie są różne ...

X44:2/1 - X57/2 (17b65e37aeeb86c8cf95643eeff70991)
X44:1/1 - X57/2 (9409cdf46bcd58d9406b44ab1cbd9c63)
X57/2 - X44:2/1 (5346a1bdddf21cbd033c3bb550de28d5)
X44:1/1 - X44:2/1 (b9b025bfe3ebcbab67f34f4e68131c66)
X57/2 - X44:1/1 (d0dafa1860b4f41d232ecb2902067df4)
X44:2/1 - X44:1/1 (a0cb3a5cc1efabec02922e89045bc531)

Gdybyś zechciał jeszcze coś podpowiedzieć ... i nie bić wstydnis.gif
Pilsener
Pokazałbyś kod, którym to robisz.

Napiszę jeszcze raz:
1. Masz tablicę, która powiedzmy wygląda tak:

Index | Pole 1 | Pole 2 | Pole n
------------------------------------
abcde|Jan|Karol|qwerty
qwerty|Karol|Jan|uiopl
zxcvb|Abcde|Xyzwe|rfcvg

Jest to tablica asocjacyjna, gdzie każdy element jest opisany indexem tekstowym oraz jest tablicą, która składa się z pole 1, pole 2, pole n.

2. Masz zrobić identyczną tablicę asocjacyjną z tym, że:
- kluczem już nie będzie np. abcde lecz md5 z JanKarol, pamiętaj o tym, że składniki klucza musisz posortować! Inaczej Jan Karol będzie różne od Karol Jan
- dotychczasowy klucz możesz zachować zapisując go jako kolejne pole o dowolnej nazwie
- tablica będzie wyglądała teraz tak:
Nowy Index | Stary Index | Pole 1 | Pole 2 | Pole n
------------------------------------
d0fbadd6b35d30e36e71e835a0aa8d7c|abcde|Jan|Karol|qwerty
d0fbadd6b35d30e36e71e835a0aa8d7c|qwerty|Karol|Jan|uiopl
4a2d95ebf80ac5e55f4678b9e80d8f2a|zxcvb|Abcde|Xyzwe|rfcvg

A ponieważ nie mogą istnieć dwa elementy o tym samym indeksie, któryś z tym "Jan Karol" zostanie wyeliminowany, który to zależy od kolejności parsowania tablicy.

Próbuj coś zrobić i podawaj koniecznie kod.
miki_kol
Witam raz jeszcze. Przepraszam Pilsener bo po treści wnioskuję że wyprowadziłem cię trochę z równowagi.
Jeśli chodzi o kod to zamieściłem go wcześniej łącznie z przedstawieniem tematu zagadnienia. Niestety Twoje rozwiązanie nie do końca było dla mnie zrozumiałe ponieważ nie wiedziałem jak pozmieniać zapisy kolumn tak jak ty to przedstawiłeś czyli

Index | Pole 1 | Pole 2 | Pole n
------------------------------------
abcde|Jan|Karol|qwerty
qwerty|Karol|Jan|uiopl
zxcvb|Abcde|Xyzwe|rfcvg

tak by te same wartości były w tych samych kolumnach.

Puenta jest taka że poradziłem sobie party.gif swoim własnym sposobem i ... jak na razie działa idealnie.

Rozwiązanie przyszło po rozpatrzeniu wszystkiego od końca czyli poprzez eliminację

przykład na podstawie tabelki - wiersze to jedna tabela, kolumny to druga tabela

  1. |aaaaa| bbbbb | ccccc | ddddd
  2. aaaaa| ------ | aaaaa-bbbbb | aaaaa-ccccc | aaaaa-ddddd
  3. bbbbb| brak | ---------- | bbbbb-ccccc | bbbbb-ddddd
  4. ccccc | brak | brak | ---------- | ccccc-ddddd
  5. ddddd| brak | brak | brak | -----------



miejsca "------" czyli wyeliminowane na wsztępie te same dane
miejsca "brak" czyli dane usunięte w kolejnych obrotach pętli by nie były brane pod uwagę

Po poskładaniu tego w całość mamy pary bez powtórzeń - w matematyce kombinatoryka bez powtórzeń

Dzięki za próbę pomocy
Pozdrawiam
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.