(я знаю, что это год спустя, но все еще полезный материал.)
Предложение Скамрадта заполнить целочисленные значения предполагает, что вы собираетесь сортировать, используя сравнение строк. Это будет медленно. Вызов формата () для каждой вставки, еще медленнее. Вместо этого вы хотите сделать целочисленное сравнение.
Вы начинаете с типа записи:
TExample = record
SortOrder : integer;
SomethingElse : string;
end;
Вы не указали, как хранились записи или как вы хотели получить к ним доступ после сортировки. Итак, давайте предположим, что вы поместили их в динамический массив:
var MyDA Array of TExample;
...
SetLength(MyDA,NewSize); //allocate memory for the dynamic array
for i:=0 to NewSize-1 do begin //fill the array with records
MyDA[i].SortOrder := SomeInteger;
MyDA[i].SomethingElse := SomeString;
end;
Теперь вы хотите отсортировать этот массив по целочисленному значению SortOrder. Если вам нужен TStringList (так что вы можете использовать метод ts.Find), тогда вы должны добавить каждую строку в список и добавить SortOrder в качестве указателя. Затем сортируйте по указателю:
var tsExamples: TStringList; //declare it somewhere (global or local)
...
tsExamples := tStringList.create; //allocate it somewhere (and free it later!)
...
tsExamples.Clear; //now let's use it
tsExamples.sorted := False; //don't want to sort after every add
tsExamples.Capacity := High(MyDA)+1 //don't want to increase size with every add
//an empty dynamic array has High() = -1
for i:=0 to High(MyDA) do begin
tsExamples.AddObject(MyDA[i].SomethingElse,TObject(MyDA[i].SortOrder));
end;
Обратите внимание на прием преобразования Integer SortOrder в указатель TObject, который хранится в свойстве TStringList.Object. (Это зависит от того факта, что Integer и Pointer имеют одинаковый размер.) Где-то мы должны определить функцию для сравнения указателей TObject:
function CompareObjects(ts:tStringList; Item1,Item2: integer): Integer;
var i,j: integer;
begin
Result := integer(ts.Objects[i]) - integer(ts.Objects[j];
end;
Теперь мы можем отсортировать tsList для .Object, вызвав .CustomSort вместо .Sort (который будет сортировать по строковому значению.)
tsExample.CustomSort(@CompareObjects); //Sort the list
TStringList теперь отсортирован, так что вы можете перебирать его от 0 до .Count-1 и читать строки в отсортированном порядке.
Но предположим, что вам не нужен TStringList, просто массив в отсортированном порядке. Или записи содержат больше данных, чем только одна строка в этом примере, и ваш порядок сортировки является более сложным. Вы можете пропустить шаг добавления каждой строки и просто добавить индекс массива как Items в TList. Сделайте все выше тем же способом, за исключением использования TList вместо TStringList:
var Mlist: TList; //a list of Pointers
...
for i:=0 to High(MyDA) do
Mlist.add(Pointer(i)); //cast the array index as a Pointer
Mlist.Sort(@CompareRecords); //using the compare function below
function CompareRecords(Item1, Item2: Integer): Integer;
var i,j: integer;
begin
i := integer(item1); //recover the index into MyDA
j := integer(item2); // and use it to access any field
Result := SomeFunctionOf(MyDA[i].SomeField) - SomeFunctionOf(MyDA[j].SomeField);
end;
Теперь, когда Mlist отсортирован, используйте его в качестве справочной таблицы для доступа к массиву в отсортированном порядке:
for i:=0 to Mlist.Count-1 do begin
Something := MyDA[integer(Mlist[i])].SomeField;
end;
Когда я перебираю TList, мы возвращаем индексы массива в отсортированном порядке. Нам просто нужно привести их обратно к целым числам, поскольку TList считает их указателями.
Мне нравится делать это таким образом, но вы также можете поместить реальные указатели на элементы массива в TList, добавив адрес элемента массива вместо его индекса. Затем, чтобы использовать их, вы приведете их в качестве указателей на записи TExample. Это то, что Барри Келли и CoolMagic сказали сделать в своих ответах.