我有一个关于Delphi StringLists的问题并对它们进行排序。我正在排序属性列表(具有重复的条目),所以我需要在排序之前保留其原始索引。这是我正在尝试的样本
procedure TestFind;
var
i, iIndex :integer;
slStrings : TStringlist;
begin
slStrings := TStringList.Create;
slStrings.Sorted := False;
slStrings.Add('Zebra');
slStrings.AddObject('Zebra',TObject(1));
slStrings.Add('Bat');
slStrings.AddObject('Bat',TObject(2));
slStrings.Add('Cat');
slStrings.AddObject('Cat',TObject(3));
slStrings.Add('Hat');
slStrings.AddObject('Hat',TObject(4));
slStrings.Add('Aat');
slStrings.AddObject('Aat',TObject(5));
slStrings.sorted := True;
if slStrings.Find('Zebra',iIndex) then
begin
while slStrings.Strings[iIndex] = slStrings.Strings[iIndex + 1] do
begin
i := ObjectToInt(slStrings.Objects[iIndex]) ;
AddMemoData ('Stringlist Found at Position: ' + inttoStr(i) + ' Current index position is: ' + inttoStr(iIndex), false);
inc(iIndex);
end;
i := ObjectToInt(slStrings.Objects[iIndex]) ;
AddMemoData ('Stringlist Found at Position: ' + inttoStr(i) + ' Current index position is: ' + inttoStr(iIndex), false);
end;
end;
当我运行这个时,我得到Zebra的值为0.8,这对我来说没有任何意义,我希望得到1,4的消息
答案 0 :(得分:2)
我真的无法弄清楚你的代码试图实现什么,但是它正在超出列表的末尾进行访问。为避免可以像这样修改while
测试:
while (iIndex<slStrings.Count-1)
and (slStrings.Strings[iIndex] = slStrings.Strings[iIndex + 1]) do
您对Objects[]
的使用将起作用。当列表排序时,放在那里的值与它们匹配的Strings[]
值保持一致。
但是,如果我是你,我不会使用字符串列表来执行此任务。我会宣布一个这样的记录:
TMyRec = record
Name: string;
Index: Integer;
end;
我会将它们保存在TList<TMyRec>
中,然后使用自定义比较器对它们进行排序。
我注意到你将每个对象添加两次,一次使用关联索引,一次不使用。后面的实例将获得默认索引值0
。我还观察到,由于我发现的越界错误,您提供的代码将无法执行。此外,即使您修复它,它也不会提供您声明的表单的输出。
换句话说,您发布的代码似乎与您运行的代码非常不同。我已根据您在问题中包含的代码回答了问题。我希望您能够在此基础上接受答案,并且不希望得到您所拥有的代码的帮助,我们无法看到。也许我应该投票结束。
无论如何,也许主要问题在于:
slStrings.Add('Zebra');
slStrings.AddObject('Zebra',TObject(1));
slStrings.Add('Bat');
slStrings.AddObject('Bat',TObject(2));
slStrings.Add('Cat');
slStrings.AddObject('Cat',TObject(3));
slStrings.Add('Hat');
slStrings.AddObject('Hat',TObject(4));
slStrings.Add('Aat');
slStrings.AddObject('Aat',TObject(5));
这相当于:
slStrings.AddObject('Zebra',TObject(0));
slStrings.AddObject('Zebra',TObject(1));
slStrings.AddObject('Bat',TObject(0));
slStrings.AddObject('Bat',TObject(2));
slStrings.AddObject('Cat',TObject(0));
slStrings.AddObject('Cat',TObject(3));
slStrings.AddObject('Hat',TObject(0));
slStrings.AddObject('Hat',TObject(4));
slStrings.AddObject('Aat',TObject(0));
slStrings.AddObject('Aat',TObject(5));
你真的是想写这个:
slStrings.AddObject('Zebra',TObject(1));
slStrings.AddObject('Bat',TObject(2));
slStrings.AddObject('Cat',TObject(3));
slStrings.AddObject('Hat',TObject(4));
slStrings.AddObject('Aat',TObject(5));
答案 1 :(得分:-1)
解决方案就是:
procedure TestFind;
var
i, iIndex, iStringSize :integer;
slStrings : TStringlist;
begin
slStrings := TStringList.Create;
slStrings.Sorted := False;
slStrings.AddObject('Zebra',TObject(1));
slStrings.AddObject('Bat',TObject(2));
slStrings.AddObject('Cat',TObject(3));
slStrings.AddObject('Hat',TObject(4));
slStrings.AddObject('Zebra',TObject(6));
slStrings.AddObject('Aat',TObject(5));
slStrings.AddObject('Zebra',TObject(7));
slStrings.sorted := True;
if slStrings.Find('Bat',iIndex) then
begin
//find lowest position of string matching found string
while iIndex > 0 do
begin
if (g_slVials.Strings[iIndex] = g_slVials.Strings[iIndex-1]) then
iIndex := iIndex - 1
else
break;
end;
iStringSize := slStrings.Count;
while iIndex < iStringSize -1 do //check for more matching strings in higher range
begin
if (g_slVials.Strings[iIndex] = g_slVials.Strings[iIndex+1]) then
begin
i := ObjectToInt(slStrings.Objects[iIndex]) ;
AddMemoData ('Stringlist Found at Position: ' + inttoStr(i) + ' Current index position is: ' + inttoStr(iIndex), false);
inc(iIndex);
end else
break;
end;
i := ObjectToInt(slStrings.Objects[iIndex]) ;
AddMemoData ('Stringlist Found at Position: ' + inttoStr(i) + ' Current index position is: ' + inttoStr(iIndex), false);
end;
end;
这允许我找到所有匹配的字符串并返回它们的索引位置