Usuwanie duplikatów z dopisaniem wartości

0

Jak zliczyć coś takiego mam w listbox dane:

a b c d e f | [a]
a b c d e f | [d]
h b c i e f | [h]
h b c i e f | [i]
{inne dane poniżej}

po lewej stronie są duplikaty i chce uzyskać jedną pozycję i dopisywać to co jest po prawej stronie

zapis ma tak wyglądać:

a b c d e f | [a][d]
h b c d e f | [h][i]

dodanie znaczników <code> - furious programming

0

Mam taki kod :

var
i : integer;
sl, sl1, sl2 : TStringList;
begin
  sl := TStringList.Create;
  sl1 := TStringList.Create;
  sl2 := TStringList.Create;

  sl.Text := ListBox1.Items.Text;

  sl2.Sorted := True;
  sl2.Duplicates := dupIgnore;

  for i := 0 to sl.Count -1  do
  begin
    sl1.Delimiter := ' ';
    sl1.DelimitedText:= sl[i];

    sl2.Add(sl1[0]+' '+sl1[1]+' '+sl1[2]+' '+sl1[3]+' '+sl1[4]+' '+sl1[5]);
  end;

  showmessage(sl2.Text);

  sl.Free;
  sl1.Free;
  sl2.Free;

tylko nie wiem jak dopisać do tego to co jest po prawej

1

Głowa jeszcze mi nie działa jak należy (wstałem niedawno), ale z tego co widzę chcesz pogrupować wiersze, które zawierają dokładnie takie same literki z lewej strony, a dopisywać jedynie literkę, znajdującą się po prawej stronie wiersza;

Twój kod jest zbyt ubogi, bo potrzebujesz według mnie dwóch pętli - jednej indeksującej wiersze od pierwszego do ostatniego, a drugiej indeksującej od wartości iteratora pierwszej pętli + 1, do ostatniego wiersza; Coś jak sortowanie bąbelkowe;

W pierwszej pętli pobierasz wiersz i przygotowujesz go do porównywania, w drugiej zaś porównujesz od od kolejnego wiersza do ostatniego; Jeśli znajdziesz wiersz z taką samą zawartością - pobierasz literkę stojącą z prawej strony i wpisujesz ją do wiersza, na który wskazuje iterator pierwszej pętli; Następnie usuwasz znaleziony wiersz i szukasz dalej; Po wykonaniu się drugiej pętli wracamy do pierwszej - pobieramy kolejny wiersz i wywołujemy drugą pętlę, która znajdzie duplikaty, pobierze ich literki i usunie wiersze;

Z racji tej, że duplikaty będą usuwane, nie możesz skorzystać z pętli For, aby nie przekroczyć zakresów; Według mnie musisz zastosować dwie pętle While i sprwadzać, czy ich iteratory mają poprawne wartości (czy nie wykonasz próby pobrania nieistniejącego wiersza);

Algorytm bardzo prosty, choć ktoś inny może mieć pomysł na coś szybszego; Ja póki co nie wybudziłem się jeszcze :]

1

@furious programming, wystarczy jedna pętla.
@Bruno(M), już naście razy ci mówiłem jak widzę nie rozumiesz. Z tym że jak czegoś nie rozumiesz to powinieneś dopytać zamiast ignorować.
Powtórzę jeszcze raz:

  1. przestań działać na stringach.
  2. Te swoje literki przedstaw jako LottoSet = set of [1..49];
  3. Funkcje konwertująca ze string do LottoSet i z powrotem są bardzo proste.
  4. To zadanie powinieneś rozwiązać na dwóch zmiennych: var src,dst:array of record Lf,Rt:LottoSet; end;
  5. Im dalej brniesz w działaniach na napisach tym dłużej działa twój kombajn.
1

@_13th_Dragon - widzę że znasz już program pytacza (ja go nie kojarzę); Ja nie pamiętam póki co poprzednich wątków i programów pytacza, więc podałem rozwiązanie, które operuje bezpośrednio na danych komponentu;

Przykład kodu, który realizuje dokładnie to, o czym napisałeś w pierwszym poście tego wątku:

procedure TForm1.btnProcessClick(Sender: TObject);
var
  intFirst, intSecond: Integer;
  strRow: AnsiString;
begin
  intFirst := 0;

  while intFirst < lbData.Items.Count - 1 do
  begin
    strRow := Copy(lbData.Items[intFirst], 1, 11);
    intSecond := intFirst + 1;

    while intSecond < lbData.Items.Count do
    begin
      if SameText(strRow, Copy(lbData.Items[intSecond], 1, 11)) then
      begin
        lbData.Items[intFirst] := lbData.Items[intFirst] + '[' +
          lbData.Items[intSecond][Length(lbData.Items[intSecond]) - 1] + ']';
        lbData.Items.Delete(intSecond);
      end
      else
        Inc(intSecond);
    end;

    Inc(intFirst);
  end;
end;

Poniżej zrzuty ekranu - po lewej przed połączeniem itemów, a po prawej już po:

duplicates.png

Jak widać działa prawidłowo, za to podane przez Ciebie dane wyjścia w pierwszym poście nie wyglądają na poprawne;

Tyle że z tego co napisał @_13th_Dragon wynika, że w komponencie nie masz wcale literek, a numery lotka, więc zarówno powyższy kod, jak i w ogóle podane przez Ciebie dane wejścia i wyjścia są wyssane nie napiszę skąd i mojego kodu nie będziesz mógł wykorzystać;

Jeśli faktycznie nadal piszesz coś związanego z lotkiem, to trzymaj dane w oddzielnych strukturach, a jedynie wyświetlaj je w komponencie; Teraz nawet nie masz jak ich posprawdzać, bo wszystko połączyłeś w łańcuchy i wpakowałeś do komponentu;

Sugeruję tak jak poprzednik trzymać zestawy sześciu liczb w zbiorze i normalnie je porównywać operatorem równości, zamiast tracić czas na ekstrakcję i dekonwersję liczb z łańcuchów z powrotem na liczby.

0

Tu chodziło o pewien proces myślowy na stringach. A liczby dla mnie to stringi :) Nie jestem programistą w tym sensie, że potrafię wszystko przełożyć na kod. Dlatego zwracam się do Was o pomoc bo wiem, że jesteście genialni. Ja chodź od 2005 roku tutaj jestem ale nadal raczkuje. Mam pomysły dobre gorzej już z kodem. Dziękuję ślicznie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1