Mega Code Archive

 
Categories / Delphi / Examples
 

Removeduplicates

Remove duplicates (from a stringlist, although the algorithm can easily be applied with other data structures). Note however that IF you're not dealing with an entity (like a string list) that handles 'pushing all subsequent items downward' (ie re-indexing) after an item has been deleted, THEN you need to code ways of dealing with that yourself... (see second example) Richard Ebbs Jan 2000 'Skeleton' code hacked from more a more extensive function, and -NOT TESTED... procedure RemoveDuplicates(inFileName: String); var counterOne: Integer; counterTwo: Integer; tempLines: TStringList; inFile: TextFile; tempStr: String; duplicateFound: Boolean; begin tempLines := TStringList.Create; if FileExists(infileName) then begin AssignFile(inFile, inFileName); ReSet(inFile); while not EOF(inFile)do begin ReadLn(inFile, tempStr); tempLines.Append(tempStr); end; counterOne := 0; while counterOne < tempLines.Count - 2 do begin counterTwo := counterOne + 1; while counterTwo < tempLines.Count - 1 do begin duplicateFound := FALSE; if (tempLines[counterOne] = tempLines[counterTwo]) then begin duplicateFound := TRUE; tempLines.Delete(counterTwo); end; if not duplicateFound then Inc(counterTwo); end; Inc(counterOne); end; {while} ReWrite(inFile); CloseFile(inFile); tempLines.SaveToFile(inFileName); end; {if} tempLines.Free; end; here's another example, looking for and removing duplicate lines in a (slightly compilicated) data structure to keep track of (drawing) lines. See below the procedure for detial on the data structure. procedure TWireFrame.RemoveDuplicateLines(var wFrameLines: TWFrameLines; ptMatrix3D: TPtMatrix3D; var linesNum: Integer); var lineIdx: Integer; counterOne: Integer; counterTwo: Integer; counterThree: Integer; duplicateFound: Boolean; AEnd1X: Real; AEnd1Y: Real; AEnd1Z: Real; AEnd2X: Real; AEnd2Y: Real; AEnd2Z: Real; BEnd1X: Real; BEnd1Y: Real; BEnd1Z: Real; BEnd2X: Real; BEnd2Y: Real; BEnd2Z: Real; begin counterOne := 0; while counterOne < linesNum - 2 do begin counterTwo := counterOne + 1; while counterTwo < linesNum - 1 do begin duplicateFound := FALSE; AEnd1X := ptMatrix3D[wFrameLines[CounterOne].endPt1].x; AEnd1Y := ptMatrix3D[wFrameLines[CounterOne].endPt1].y; AEnd1Z := ptMatrix3D[wFrameLines[CounterOne].endPt1].z; AEnd2X := ptMatrix3D[wFrameLines[CounterOne].endPt2].x; AEnd2Y := ptMatrix3D[wFrameLines[CounterOne].endPt2].y; AEnd2Z := ptMatrix3D[wFrameLines[CounterOne].endPt2].z; BEnd1X := ptMatrix3D[wFrameLines[CounterTwo].endPt1].x; BEnd1Y := ptMatrix3D[wFrameLines[CounterTwo].endPt1].y; BEnd1Z := ptMatrix3D[wFrameLines[CounterTwo].endPt1].z; BEnd2X := ptMatrix3D[wFrameLines[CounterTwo].endPt2].x; BEnd2Y := ptMatrix3D[wFrameLines[CounterTwo].endPt2].y; BEnd2Z := ptMatrix3D[wFrameLines[CounterTwo].endPt2].z; if ((Floor(AEnd1X) = Floor(BEnd1X)) and (Floor(AEnd1Y) = Floor(BEnd1Y)) and (Floor(AEnd1Z) = Floor(BEnd1Z)) and (Floor(AEnd2X) = Floor(BEnd2X)) and (Floor(AEnd2Y) = Floor(BEnd2Y)) and (Floor(AEnd2Z) = Floor(BEnd2Z))) then begin duplicateFound := TRUE; //now effectively delete wFrameLines[CounterTwo] //by effectively re-indexing the wFrameLines data //structure such that all subsequent wFrameLines //entries are shifted 'upwards' for counterThree := (counterTwo + 1) to linesNum do begin wFrameLines[counterThree - 1] := wFrameLines[counterThree]; end; Dec(linesNum); end; if not duplicateFound then Inc(counterTwo); end; Inc(counterOne); end; {while} end; The 'ptMatrix3D' data structure holds POINTS data. The 'wFrameLines' (ie wireFrame lines) data structure keeps track of the LINES between the points. Each wFrameLines record in the array has integer fields for 'endpoints' which are simply indexes into the ptMatrix array. To access a (coordinate) value from the point matrix relating to a particular line, we would use syntax like this: x := wireFrame.ptMatrix3D[wireFrame.wFrameLines[lineIdx].endPt1].x; y := wireFrame.ptMatrix3D[wireFrame.wFrameLines[lineIdx].endPt1].y; where x and y are both Real values. Happy hunting.