TListBox组件包含一组行(字符串)。如何将此设置作为列表TList?下面的代码示例不会给出所需的结果。 (Сode不编译)
MyList := TList<String>.Create(MyListBox);
MyList := TList<String>.Create(MyListBox.Items);
MyList := TList<String>.Create(MyListBox.Items.ToStringArray);
是否可以在不使用循环的情况下执行此操作? 谢谢!
答案 0 :(得分:5)
你可以这样做:
MyList := TList<string>.Create;
try
MyList.AddRange(MyListBox.Items.ToStringArray);
....
finally
MyList.Free;
end;
如果您想在构造函数中分配项目,则需要TEnumerable<string>
的实例。从外面移植到TStrings
并不容易。所以我认为上面的代码可能是最干净的。
答案 1 :(得分:3)
大卫的回答很简单,如果你不介意分配一个额外的数组来保存被复制的字符串的临时副本。如果你想减少内存使用量,特别是如果列表很大,循环更好:
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;
当然,并不像David的回答那么优雅,但是枚举器旨在帮助简化循环列表项(从而允许创建for..in
循环语法)。