Deleting duplicates in Delphi listview
I am trying to remove duplicates in my listview.
This function:
procedure RemoveDuplicates(const LV:TbsSkinListView);
var
i,j: Integer;
begin
LV.Items.BeginUpdate;
LV.SortType := stText;
try
for i := 0 to LV.Items.Count-1 do
begin
for j:=i+1 to LV.Items.Count-1 do
begin
if SameText(LV.Items[i].SubItems[0], LV.Items[j].SubItems[0]) and
SameText(LV.Items[i].SubItems[1], LV.Items[j].SubItems[1]) and
开发者_运维技巧 SameText(LV.Items[i].SubItems[2], LV.Items[j].SubItems[2]) and
SameText(LV.Items[i].SubItems[3], LV.Items[j].SubItems[3]) then
LV.Items.Delete(j);
end;
end;
finally
LV.SortType := stNone;
LV.Items.EndUpdate;
end;
ShowMessage('Deleted');
end;
does not delete the duplicates. What is wrong with it?
At a guess, since you haven't mentioned what is going wrong, I would think that is has to do with the fact that i
and j
are invalid after you have deleted an item because you are counting UP.
A better idea would be to count down instead:
procedure RemoveDuplicates(const LV:TbsSkinListView);
var
i,j: Integer;
begin
LV.Items.BeginUpdate;
LV.SortType := stText;
try
for i := LV.Items.Count-1 downto 0 do // <- this loop now counts _down_
begin
for j:= LV.Items.Count-1 downto i+1 do // <- this loop now counts _down_
begin
if SameText(LV.Items[i].SubItems[0], LV.Items[j].SubItems[0]) and
SameText(LV.Items[i].SubItems[1], LV.Items[j].SubItems[1]) and
SameText(LV.Items[i].SubItems[2], LV.Items[j].SubItems[2]) and
SameText(LV.Items[i].SubItems[3], LV.Items[j].SubItems[3]) then
LV.Items.Delete(j);
end;
end;
finally
LV.SortType := stNone;
LV.Items.EndUpdate;
end;
ShowMessage('Deleted');
end;
The easiest way to do this in Delphi IMO is to do it like this....
- Create a function that creates a hashkey for your matching critera i.e. add all the text you want to match together and then hash it.
- use the hash as a key in a list
- navigate your listview and remove any item that is not in the list.
Pseudo Code....(untested)
var
hash : integer;
i : integer;
list : SomeGenericList; // some generic list to contain your hash.
Begin
list = SomeGenericList.Create;
for i := pred(lv.Items.Count) downto 0
begin
hash := GetHashValue(lv.items[i]);
if List.Contains(hash)
begin
lv.Items.Delete(i);
end else
begin
List.Add(hash);
end;
end;
list.free;
end;
Shame delphi does not have Linq type functionality, this would be a really simple task using that.
精彩评论