2012-08-31 41 views
0

说我有从组合框中删除重复

apples 
apples 
pears 
oranges 
oranges 

的组合框我想有它显示

apples 
pears 
oranges 

我怎么能做到这一点?

+0

Zarko在这方面有很好的文章。 http://delphi.about.com/od/delphitips2009/qt/remove-duplicat.htm –

+0

@GX - 建议代码的副作用可能会改变字符串的顺序。 – Igor

回答

5
for iter := combobox.Items.Count - 1 downto 0 do 
begin 
    index := combobox.Items.IndexOf(combobox.Items[iter]); 
    if index < iter then 
    combobox.Items.Delete(iter); 
end; 
+0

感谢工作,不得不添加溶解氧,但其他然后,它是好.. –

+0

哎呀,直接输入SO。将for循环包装在combobox.Items.BeginUpdate/combobox.Items.EndUpdate中以获得性能。 – Igor

+0

虽然这是一种有效且简单的方法,但请注意在较大的列表中使用此方法。即使只有几千个条目,这种方法也会变得非常慢。 –

2

我建议你每次只需重新填充组合框。这使得逻辑更简单:

ComboBox.Items.BeginUpdate; 
try 
    ComboBox.Clear; 
    for Str in Values do 
    begin 
    if ComboBox.Items.IndexOf (Str) = -1 then 
     ComboBox.Items.Add (Str); 
    end; 
finally 
    ComboBox.Items.EndUpdate; 
end; 
0

您必须从源数据中删除重复项。

在大多数情况下,ComboBox在运行时充满了数据,这意味着数据来自某个源。这里基本上有两种情况:来自数据库的数据集和来自任何其他来源的字符串集合。在这两种情况下,在将任何内容插入到组合框之前,都会过滤出重复项。

如果源是数据库中的数据集,只需使用SQL DISTINCT关键字即可。

如果source是任何字符串集合,请使用@Smasher在答案中提供的代码。

2

只是为了对抗海誓山盟:一个保持秩序,但越来越慢的项目数量较多。其他保持相对较快,但不会维持秩序:

procedure SortStringlist; 
var 
    i,index,itimer: integer; 
    sl : TStringlist; 
const 
    numberofitems = 10000; 
begin 
    sl := TStringlist.Create; 
    for i := 0 to numberofitems-1 do begin 
    sl.Add(IntToStr(random(2000))); 
    end; 
    Showmessage(IntToStr(sl.Count)); 

    itimer := GetTickCount; 
    sl.Sort; 
    for I := sl.Count-1 downto 1 do begin 
    if sl[i]=sl[i-1] then sl.Delete(i); 
    end; 
    Showmessage(IntToStr(sl.Count)+' Time taken in ms: '+IntToStr(GetTickCount-itimer)); 
    sl.free; 
    sl := TStringlist.Create; 
    for i := 0 to numberofitems-1 do begin 
    sl.Add(IntToStr(random(2000))); 
    end; 
    Showmessage(IntToStr(sl.Count)); 

    itimer := GetTickCount; 
    for i := sl.Count - 1 downto 0 do 
    begin 
    index := sl.IndexOf(sl[i]); 
    if index < i then 
    sl.Delete(i); 
    end; 
    Showmessage(IntToStr(sl.Count)+' Time taken in ms: '+IntToStr(GetTickCount-itimer)); 
end; 
+0

不要忘记使用'尝试SL.BeginUpdate..finally SL.EndUpdate'来锁定更新。 – TLama

+0

非视觉对象需要吗? –

+0

对不起,收回。 'TStringList'没有必要,我把你的'SL'弄错了。我不得不休息一下:-) – TLama

2

如果如果项目将重新排序不关心(或者他们已经排序),TStrings能为你做的工作 - 它消除了所有的循环,删除和其他工作。 (当然,这需要一个临时TStringList的创建/销毁,所以如果这是你的问题,它不会工作。)

var 
    SL: TStringList; 
begin 
    ComboBox1.Items.BeginUpdate; 
    try 
    SL := TStringList.Create; 
    try 
     SL.Sorted := True; // Required for Duplicates to work 
     SL.Duplicates := dupIgnore; 
     SL.AddStrings(ComboBox1.Items); 
     ComboBox1.Items.Assign(SL); 
    finally 
     SL.Free; 
    end; 
    finally 
    ComboBox1.Items.EndUpdate; 
    end; 
end; 

要正确伊戈尔的答案(这不包括BeginUpdate/EndUpdate)比较,删除那些事:

var 
    SL: TStringList; 
begin 
    SL := TStringList.Create; 
    try 
    SL.Sorted := True; // Required for Duplicates to work 
    SL.Duplicates := dupIgnore; 
    SL.AddStrings(ComboBox1.Items); 
    ComboBox1.Items.Assign(SL); 
    finally 
    SL.Free; 
    end; 
end; 
0

我前几次遇到这样的问题,我使用所有的以前的办法,我仍然使用它们,但你知道:我认为最好的办法,虽然这里没有提到,是为子类TComboBox,创建一个新的方法(比如AddUnique),如果它以前不存在,则只将该字符串添加到组合中,其他明智的,它会放弃它。 该解决方案一开始可能会花费一些额外的时间,但它会一劳永逸地解决问题。