Конвертировать строки в ListBox в List<String>
Компонент TListBox содержит набор строк (строк). Как я могу получить этот набор в виде списка TList? Примеры кода, приведенные ниже, не дают желаемого результата. (Код не компилируется)
MyList := TList<String>.Create(MyListBox);
MyList := TList<String>.Create(MyListBox.Items);
MyList := TList<String>.Create(MyListBox.Items.ToStringArray);
Возможно ли это сделать без использования цикла или нет? Спасибо!
2 ответа
Вы можете сделать это:
MyList := TList<string>.Create;
try
MyList.AddRange(MyListBox.Items.ToStringArray);
....
finally
MyList.Free;
end;
Если вы хотите назначить элементы в конструкторе, вам понадобится экземпляр TEnumerable<string>
, Это не легко привить к TStrings
снаружи. Поэтому я думаю, что приведенный выше код, вероятно, самый чистый.
Ответ Дэвида прост, если вы не возражаете против выделения дополнительного массива для временной копии копируемых строк. Если вы хотите уменьшить использование памяти, особенно если список большой, цикл лучше:
var
MyList: TList<String>;
I: Integer;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
for i := 0 to MyList.Capacity-1 do
MyList.Add(MyListBox.Items[I]);
...
finally
MyList.Free;
end;
end;
В качестве альтернативы:
var
MyList: TList<String>;
S: String;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
for S in MyListBox.Items do
MyList.Add(S);
...
finally
MyList.Free;
end;
end;
Однако, если вы не хотите выполнять цикл вручную, я бы предложил создать пользовательский перечислитель, чтобы вы могли передать TStrings
данные непосредственно в TList<String>
и пусть он скопирует строки для вас:
type
TStringsEnumeratorWrapper = class(TEnumerator<String>)
protected
FEnum: TStringsEnumerator;
function DoGetCurrent: String; override;
function DoMoveNext: Boolean; override;
public
constructor Create(AStrings: TStrings);
destructor Destroy; override;
end;
constructor TStringsEnumeratorWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FEnum := AStrings.GetEnumerator;
end;
destructor TStringsEnumeratorWrapper.Destroy;
begin
FEnum.Free;
inherited Destroy;
end;
function TStringsEnumeratorWrapper.DoGetCurrent: String;
begin
Result := FEnum.Current;
end;
function TStringsEnumeratorWrapper.DoMoveNext: Boolean;
begin
Result := FEnum.MoveNext;
end;
type
TStringsEnumerableWrapper = class(TEnumerable<String>)
protected
FStrings: TStrings;
function DoGetEnumerator: TEnumerator<T>; override;
public
constructor Create(AStrings: TStrings);
end;
constructor TStringsEnumerableWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FStrings := AStrings;
end;
function TStringsEnumerableWrapper.DoGetEnumerator: TEnumerator<T>;
begin
Result := TStringsEnumeratorWrapper.Create(FStrings);
end;
var
MyList: TList<String>;
Enum: TStringsEnumerableWrapper;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
Enum := TStringsEnumerableWrapper.Create(MyListBox.Items);
try
MyList.AddRange(Enum);
finally
Enum.Free;
end;
...
finally
MyList.Free;
end;
end;
В качестве альтернативы:
type
TStringsEnumeratorWrapper = class(TObject, IEnumerator<String>)
protected
FEnum: TStringsEnumerator;
public
constructor Create(AStrings: TStrings);
destructor Destroy; override;
function GetCurrent: String;
function MoveNext: Boolean;
procedure Reset;
end;
constructor TStringsEnumeratorWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FEnum := AStrings.GetEnumerator;
end;
destructor TStringsEnumeratorWrapper.Destroy;
begin
FEnum.Free;
inherited Destroy;
end;
function TStringsEnumeratorWrapper.GetCurrent: String;
begin
Result := FEnum.Current;
end;
function TStringsEnumeratorWrapper.MoveNext: Boolean;
begin
Result := FEnum.MoveNext;
end;
procedure TStringsEnumeratorWrapper.Reset;
begin
//FEnum.Reset;
end;
type
TStringsEnumerableWrapper = class(TObject, IEnumerable<String>)
protected
FStrings: TStrings;
public
constructor Create(AStrings: TStrings);
function GetEnumerator: IEnumerator<String>;
end;
constructor TStringsEnumerableWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FStrings := AStrings;
end;
function TStringsEnumerableWrapper.GetEnumerator: IEnumerator<String>;
begin
Result := TStringsEnumeratorWrapper.Create(FStrings);
end;
var
MyList: TList<String>;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
MyList.AddRange(TStringsEnumerableWrapper.Create(MyListBox.Items));
...
finally
MyList.Free;
end;
end;
Конечно, не так элегантно, как ответ Дэвида, но счетчики были разработаны, чтобы упростить циклический просмотр элементов списка (и, таким образом, позволили создать for..in
Синтаксис цикла).