2

TListBox コンポーネントには、一連の行 (文字列) が含まれています。このセットをリスト TList として取得するにはどうすればよいですか? 以下のコード例では、目的の結果が得られません。(コードはコンパイルされません)

MyList  := TList<String>.Create(MyListBox);
MyList  := TList<String>.Create(MyListBox.Items);
MyList  := TList<String>.Create(MyListBox.Items.ToStringArray);

ループを使用せずにこれを行うことは可能ですか? ありがとう!

4

2 に答える 2

5

あなたはこれを行うことができます:

MyList := TList<string>.Create;
try
  MyList.AddRange(MyListBox.Items.ToStringArray);
  ....
finally
  MyList.Free;
end;

コンストラクターで項目を割り当てたい場合は、のインスタンスが必要ですTEnumerable<string>TStrings外側から移植するのは簡単ではありません。したがって、上記のコードがおそらく最もクリーンだと思います。

于 2013-08-08T08:56:40.933 に答える
3

コピーされる文字列の一時コピーを保持するために余分な配列が割り当てられることを気にしないのであれば、Davidの答えは簡単です。特にリストが大きい場合、メモリ使用量を減らしたい場合は、ループの方が適しています。

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ループ構文の作成を可能にしました)。

于 2013-08-09T03:43:18.427 に答える