Results 1 to 9 of 9

Thread: Tstringlist probleem

  1. #1
    Senior Member
    Join Date
    May 2009
    Location
    End of the Road
    Posts
    893

    Tstringlist probleem

    Ik ben bezig met iets heel simpels, en zit er nu uren naar de kijken, maar krijg
    het niet werkend.

    Ik heb 2 Stringlists, waarvan ik het verschil in een 3e Stringlist wil zetten.
    Niet echt moeilijk, maar zal denk ik wel door het vele turen zijn..

    Kan iemand mij vertellen wat ik hier mis or verkeerd doe?

    Thanks


    Code:
    my1:=tstringlist.Create;
    my2:=tstringlist.Create;
    my3:=tstringlist.Create;
    my1.Sorted :=true;
    my2.Sorted:=true;
    
    my1 heeft de nummers    1,2,5,6,9,10
    my2 heeft de nummers    1,2,3,4,5,6,7,8,9,10
    
    dus my3 moet dan worden  3,4,7,8
    
    ii:=0;
    for i:=0 to 5 do  // 5 =  my1.count-1
       begin        
       if my1[i]<>my2[ii] then
          begin
          my3.add(my2[ii]);
          // de repeat - loop zit erin, zodat als er een nummer ontbreekt
          // hij skipped naar de volgende totdat hij hetzelfde is
          repeat
          ii:=ii+1;
          until (my1[i]=my2[ii]) or (i>=ii);
          end;
          ii:=ii+1;
     end;

    //1 vs 1
    //2 vs 2

    //5 vs 3
    // ongelijk dus Add 3 en 4 in de andere lijst en maak ii = 5

    //6 vs 4
    //7 vs 5
    //8 vs 6
    //9
    //10

    //10

  2. #2
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Waarom TStringlist. Dit is echt overkill. Maar dat terzijde.
    Maak gebruik van TStringlist.items.indexof(). Dan zoek je naar een index. als deze niet bestaat, heb je je nummer, die je mist.
    delphi Code:
    1. procedure compare;
    2. var sl1, sl2, sl3 : TStringList;
    3.     teller        : byte;
    4. begin
    5.   sl1 := TStringlist.Create;
    6.   sl2 := TStringlist.Create;
    7.   sl3 := TStringlist.Create;
    8.   try
    9.     sl1.CommaText := '1,2,5,6,9,10';
    10.     sl2.CommaText := '1,2,3,4,5,6,7,8,9,10';
    11.     for teller := 0 to sl2.Count - 1 do
    12.     begin
    13.       if sl1.IndexOf(sl2[teller]) = -1 then
    14.         sl3.Add(sl2[teller]);
    15.     end;
    16.     showmessage(sl3.CommaText);
    17.   finally
    18.     sl1.Free;
    19.     sl2.Free;
    20.     sl3.Free;
    21.   end;
    22. end;
    Last edited by jkuiper; 16-Sep-11 at 10:33.
    Delphi is great. Lazarus is more powerfull

  3. #3
    Waarom is TStringList overkill? Volgens mij is het juist heel handig voor dit soort dingen.

    Ik heb er een keer één gemaakt die ook zoiets doet, maar die werkte niet op een gesorteerde lijst. Je kunt de lijst natuurlijk sorteren om het sneller te maken, maar het doel was in dit geval om de volgorde wel hetzelfde te houden.

    Ik heb het toen gebruikt om twee scripts te vergelijken waarin iemand een hoop had zitten schuiven. Met dit tooltje kon ik de regels vinden die überhaupt niet in het oude scriptje voorkwamen, en zodoende zien wat er nou eigenlijk echt veranderd was.

    Optimaal is het niet, maar het heet dan ook QDSC, Quick&Dirty Script Comparison.

    Delphi Code:
    1. var
    2.   sl1, sl2, slt: TStringList;
    3.   i: Integer;
    4.   ndx: Integer;
    5. begin
    6.   sl1 := TStringList.Create;
    7.   sl2 := TStringList.Create;
    8.   slt := TStringList.Create;
    9.   try
    10.     sl1.Text := Memo1.Text;
    11.     sl2.Text := Memo2.Text;
    12.  
    13.     // Check each line in 2 if it exists in 1. If not, add it to t.
    14.     // If lines match, remove it from 1, so similar lines are only matched once.
    15.     for i := 0 to sl2.Count - 1 do
    16.     begin
    17.       if Trim(sl2[i]) <> '' then
    18.       begin
    19.         ndx := sl1.IndexOf(sl2[i]);
    20.         if ndx = -1 then
    21.           slt.Add(sl2[i])
    22.         else
    23.           sl1.Delete(ndx);
    24.       end;
    25.     end;
    26.  
    27.     // Show the lines that didn't match in the first memo.
    28.     Memo1.Text := slt.Text;
    29.  
    30.   finally
    31.     sl1.Free; sl2.Free; slt.Free;
    32.  
    33.   end;
    Attached Files Attached Files
    1+1=b

  4. #4
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Een script vergelijken is toch een ander verhaal dan een reeks nummers. Datt kan met een array namelijk ook.
    delphi Code:
    1. procedure comparray;
    2. const a1 : array[0..5] of integer = (1,2,5,6,9,10);
    3.       a2 : array[0..9] of integer = (1,2,3,4,5,6,7,8,9,10);
    4. var a3 : array of integer;
    5.     teller, ateller : byte;
    6.     msg : string;
    7.  
    8. function cmp(value : integer) : boolean;
    9. var teller : byte;
    10.     found : byte;
    11. begin
    12.   found := 0;
    13.   for teller := 0 to length(a1) - 1 do
    14.   begin
    15.     if value = a1[teller] then
    16.      found := found + 1;
    17.   end;
    18.   result := found > 0;
    19. end;
    20.  
    21. begin
    22.   ateller := 0;
    23.   for teller := 0 to length(a2) - 1 do
    24.   begin
    25.     if not cmp(a2[teller]) then
    26.     begin
    27.       ateller := ateller + 1;
    28.       Setlength(a3,ateller);
    29.       a3[high(a3)] := a2[teller];
    30.       msg := msg + inttostr(a3[high(a3)]) + ' ';
    31.     end;
    32.   end;
    33.   showmessage(msg);
    34. end;
    Vaak is de discussie geweest wanneer je eigenlijk een stringlist moet gebruiken. Ik vind het zelf ook handiger, omdat er genoeg functionaliteit in zit. Scheelt een hoop werk.
    Ik weet bijna zeker dat Marcov zal kiezen voor een array (heb ik gelezen in een een topic). Maar niets is zeker, toch
    Delphi is great. Lazarus is more powerfull

  5. #5
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Organizer, je hebt al mooie oplossingen van andere dierebare Delphibroeders hierboven, maar mocht je willen weten wat je nu fout gedaan hebt, ziehier:

    delphi Code:
    1. for i:=0 to 5 do  // 5 =  my1.count-1
    2.    begin        
    3.    if my1[i]<>my2[ii] then
    4.       begin
    5.       my3.add(my2[ii]); <-- Vanaf het ogenblik dat je één string in my1 vindt dat verschillend is van je my2-string, voeg je het reeds toe.

    Beter:
    Delphi Code:
    1. gevonden := false ;
    2. for i:=0 to 5 do  // 5 =  my1.count-1
    3.    if my1[i]=my2[ii] then
    4.       gevonden := true ;
    5.  if not gevonden then
    6.   my3.add(my2[ii])

    Hier voeg je de my2-string pas toe als je hem niet gevonden heb in de gehele stringlist my1.
    Zet dit geheel in een lus zodat dit uitgevoerd wordt voor alle strings in my2, en je hebt je resultaat.
    Niet beter dan de voorgaande oplossingen, maar zo zie je waar je de verkeerde kant op ging
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  6. #6
    Senior Member
    Join Date
    May 2009
    Location
    End of the Road
    Posts
    893
    Bedankt allemaal voor jullie help.
    En Bedankt SamWitse voor de uitleg. Kweet nu precies wat ik verkeerd had
    gedaan.

  7. #7
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Een beetje aan de late kant maar je maakt het je zelf ERG lastig door met stringlists te werken.

    Er is een SET operatie in Delphi die dit voor kleine sets kan (voor grotere ook geloof ik, dan gebruik je TBITS). Vergelijk de lengte van het eerste met de tweede (al zit daar de eerste ook in)

    In essentie is de eerste source 3 regels, de rest is printen en variabele declaratie

    Delphi Code:
    1. program testset;
    2.  
    3. {$ifdef FPC}
    4.  {$mode delphi}
    5. {$else}
    6.  {$apptype console}
    7. {$endif}
    8. uses classes,sysutils;
    9.  
    10. const setmax = 20;
    11.  
    12. Type TSomeSet = set of 0..setmax;
    13.  
    14. procedure printset(inset:TSomeSet);
    15. var i : integer;
    16. begin
    17.   for i:=0 to setmax do
    18.     if i in inset then
    19.       writeln(i);
    20.  end;
    21.  
    22. var
    23.     set1,set2,set3:tsomeset;
    24. begin
    25.   set1:=[1,2,5,6,9,10];
    26.   set2:=[1,2,3,4,5,6,7,8,9,10];
    27. // (set1+set2 = combinatie van beide sets) - (set1 * set2 = gezamelijke delen set1 en 2)
    28.   set3:=(set1+set2)-(set1*set2);    
    29.   printset(set3);
    30.   readln;
    31. end.


    Delphi Code:
    1. program testset;
    2.  
    3. {$ifdef FPC}
    4.  {$mode delphi}
    5. {$else}
    6.  {$apptype console}
    7. {$endif}
    8. uses classes,sysutils;
    9.  
    10. const setmax = 20;
    11.  
    12. Type
    13.     TSomeSet = set of 0..setmax;
    14.  
    15. const
    16.    unionset : TSomeSet = [0..setmax];
    17.  
    18. function StringlistToSet(s:TStringlist):TSomeSet;
    19.  
    20. var i,j : integer;
    21. begin
    22.   result:=[];
    23.   for i:=0 to s.count-1 do
    24.     begin
    25.       if trystrtoint(s[i],j)then
    26.         if (j>0) and (j<=setmax) then
    27.           include(result,j);
    28.     end;
    29. end;
    30.  
    31. procedure SetToStringList(inset:TSomeSet;var OutList : TStringList);
    32. var i : integer;
    33. begin
    34.   if not assigned(outlist) then
    35.     exit;
    36.   outlist.clear;
    37.   for i:=0 to setmax do  
    38.     if i in inset then
    39.       outlist.add(inttostr(i));
    40. end;
    41.  
    42. procedure printStringList(OutList : TStringList);
    43. var i : integer;
    44. begin
    45.   if not assigned(outlist) then
    46.     exit;
    47.   outlist.clear;
    48.   for i:=0 to outlist.count-1 do  
    49.     writeln(outlist[i]);
    50. end;
    51.  
    52. // van hier
    53.  
    54. procedure printset(inset:TSomeSet);
    55. var i : integer;
    56. begin
    57.   for i:=0 to setmax do
    58.     if i in inset then
    59.       writeln(i);
    60.  end;
    61.  
    62.  
    63. var my1,my2,my3:tstringlist;
    64.     set1,set2,set3:tsomeset;
    65. begin
    66.   set1:=[1,2,5,6,9,10];
    67.   set2:=[1,2,3,4,5,6,7,8,9,10];
    68.  
    69.   set3:=(set1+set2)-(set1*set2);    // (set1+set2 = combinatie van beide sets) - (set1 * set2 = gezamelijke delen set1 en 2)
    70.   printset(set3);
    71.  
    72. // tot hier is alles wat nodig is.
    73.  
    74. // opzetten data gaat makkelijker vanaf set
    75.   my1:=tstringlist.Create;
    76.   settostringlist(set1,my1);
    77.   my2:=tstringlist.Create;
    78.   settostringlist(set2,my2);
    79.   my3:=tstringlist.Create;
    80.  
    81. // dan hetzelfde voor stringlists
    82.   set1:=stringlisttoset(my1);
    83.   set2:=stringlisttoset(my2);   // converteer naar set.
    84.   set3:=(set1+set2)-(set1*set2);             // bereken het verschil
    85.   settostringlist(set3,my3);    // terug naar stringlist
    86.  
    87.   printstringlist(my3);
    88.   readln;
    89. end.

  8. #8
    Senior Member
    Join Date
    May 2009
    Location
    End of the Road
    Posts
    893
    Bedankt Marco,

    Zal er is naar kijken vanavond. Het gaat in my geval op 7000 nummers.

  9. #9
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Dan moet je TBits gaan gebruiken. Maar eerlijk gezegd heb ik dat nooit gedaan in Delphi.

    Heb de klasse wel vaker gebruikt in FPC, maar ik weet dat ie uitgebreid is. De clou is dat de basis formule effectief

    (x1 or x2) - (x1 and x2)

    is.

    Indien de Delphi TBits te beperkt, even naar alternatieven zoeken. Die moeten er wel zijn, dit is een oude classe.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •