Хорошо, как мы нашли в комментариях, у нас есть 2 задачи:
- Как узнать, содержит ли уже элемент
TObjectList
(поэтому новый элемент является дубликатом)
- Как управлять значками файлов в
TImageList
, чтобы уменьшить использование памяти и хранить только уникальные значки.
Как я упоминал в комментариях, вы должны задать свой второй вопрос в отдельной ветке, но я предлагаю вам добавить новые значки файлов в зависимости от нового типа mime файла вместо двоичных данных значка. Здесь вам нужно создать словарь файлового типа, определить тип файла и так далее.
Как насчет дубликатов в TObjectList
. Вы, наверное, знаете, что существует generic
реализация TObjectList
- TObjectsList<T>
. Как и в вашем примере, вы можете определить TPersonList
как TObjectList<TPerson>
, поэтому свойство items
всегда возвращает экземпляр объекта TPerson
.
теперь общая задача со списками - сортировка списка. Взгляните на Sort()
метод TObjectList<T>/TList
. Он имеет 2 метода перегрузки. Один из них используется по умолчанию, а второй принимает в качестве параметра Comparer
. Собственно, первый метод тоже использует компаратор — компаратор по умолчанию. Таким образом, компаратор - это реализация интерфейса IComparer<T>
, который имеет единственный метод - function Compare(l,r : T):integer
; Обычно этот компаратор сортировки определяется во время выполнения как анонимный метод перед вызовом метода Sort()
. Используя ваш анонимный метод, вы всегда знаете, как сравнить два объекта типа T
, и тогда вы можете определить, какой из них "больше" другого и должен быть первым в списке.
поэтому та же ситуация, что и при поиске дубликатов в списке. но теперь вы должны определить, равны ли 2 объекта или нет.
Предположим, у вас есть personList : TPersonList
, который содержит TPerson
экземпляров. У каждого человека есть, например, имя, фамилия, дата рождения и удостоверение личности. Конечно, компаратор по умолчанию ничего не знает о том, как сравнивать 2 человека. Но вы можете предоставить новый компаратор, который знает. Например, предположим, что 2 объекта равны, если их идентификаторы равны;
TPerson = class(TObject)
strict private
FName : string;
FSurname : string;
FDateOfBirth : TDateTime;
FId : string; {passport number or something else}
public
constructor Create(aID : string; aDoB : TDateTime);
property Name : string read FName write FName;
property Surname : string read FSurname write FSurname;
property DateOfBirth : TDateTime read FDateOfBirth;
property ID : string read FId;
end;
TPersonList = class(TObjectList<TPerson>)
public
constructor Create();
end;
TPerson
конструктор обычный:
constructor TPerson.Create(aID: string; aDoB: TDateTime);
begin
inherited Create();
FID := aId;
FDateOfBirth := aDoB;
end;
теперь нам нужно написать TPersonList
конструктор. Как видите, у конструктора TObejctList
мало перегрузок. Один из них имеет параметр Comparer
. Он сохраняет aComparer
в поле FComparer
. Теперь взгляните на метод Contains
. Он находит, содержит ли список уже объект или нет. Он использует метод IndexOf
. Итак, если возвращаемый индекс = 0, то список содержит наш объект.
Итак, теперь наша задача — определить новый компаратор в конструкторе TPersonList
. Мы должны определить метод сравнения, затем создать объект сравнения и передать его конструктору списка.
constructor TPersonList.Create();
var comparer : IComparer<TPerson>;
comparison : TComparison<TPerson>;
begin
comparison := function(const l,r : TPerson):integer
begin
if l.ID = r.id then exit(0)
else if l.ID > r.ID then exit(-1)
else exit(1);
end;
comparer := TComparer<TPerson>.Construct(comparison);
inherited Create(comparer);
end;
чтобы протестировать наш код, давайте добавим в список несколько человек.
procedure TForm2.FormCreate(Sender: TObject);
var persons : TPersonList;
function AddPerson(id : string; date : TDateTime):boolean;
var p : TPerson;
begin
p := TPerson.Create(id, date);
result := not persons.Contains(p);
if result then
persons.Add(p)
else begin
ShowMessage('list already contains person with id = ' + id);
p.Free();
end;
end;
begin
persons := TPersonList.Create();
try
AddPerson('1', StrToDate('01.01.2000'));
AddPerson('2', StrToDate('01.01.2000'));
AddPerson('3', StrToDate('01.01.2000'));
AddPerson('2', StrToDate('01.01.2000')); // we will get message here.
finally
persons.Free();
end;
end;
Итак, это обычный способ определить, содержит ли TList
(или его потомок) объект.
person
teran
schedule
04.01.2013
IndexOf
илиContains
. Эти методы уже существуют вTList<T>
универсальном контейнере. - person David Heffernan   schedule 04.01.2013TFindDuplicates
являетсяprocedure of object
, но вы передаетеFindDuplicates
, который является обычным методом (то есть: неof object
) и также является не процедурой, а функцией. Один из двух должен быть изменен для компиляции. - person J...   schedule 04.01.2013TImageList
. У вас есть список файлов, и каждый файл имеет свою иконку (HICON
). Вы собираетесь заполнитьTImageList
этими значками и вернутьImageIndex
. Итак, еслиImageList
уже имеет значок, подобный вашему новому файлу, вы хотите использовать этот существующийImageIndex
, не добавляя новый значок вImageList
. так. вопрос: это ваша проблема или нет? если да, спросите о вашей конкретной проблеме. если нет, то зачем вы вставили сюда код патебина? - person teran   schedule 04.01.2013exe
иlnk
. Итак, предложение - заполнить список изображений в зависимости от типа файла вместо двоичных данных значка. - person teran   schedule 04.01.2013