2
function TSomething.Concat<T>(const E: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
begin
  Result := TConcatIterator<T>.Create(E) as IEnumerable<T>;
end;

2 つの列挙型しか連結できないため、これはコンパイルされませんTConcatIterator<T>が、列挙型の列挙型を連結する反復子が必要です。

Haskell には、concatこれを行う関数があります。

concat [[1, 2, 3], [4,5]] => [1, 2, 3, 4, 5]

Delphi バージョンは次のようになります。

class function TForm1.Concat<T>(
  const AEnumerable: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
begin
  // ???
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  InnerList1: IList<Integer>;
  InnerList2: IList<Integer>;
  OuterList: IList<IEnumerable<Integer>>;
  Concated: IEnumerable<Integer>;
begin
  InnerList1 := TCollections.CreateList<Integer>([1, 2, 3]);
  InnerList2 := TCollections.CreateList<Integer>([4, 5]);
  OuterList := TCollections.CreateList<IEnumerable<Integer>>([InnerList1, InnerList2]);
  Concated := Concat<Integer>(OuterList);
end;

これをspring4dで実装するにはどうすればよいですか?

4

2 に答える 2

4

Spring4D コレクションは .Net のコレクションに基づいてモデル化されているため、探している操作/メソッドはSelectManyと呼ばれます。

1.2 では、TEnumerable型にそのための静的メソッドがあるため、コードは次のようになります。

Concated := TEnumerable.SelectMany<IEnumerable<Integer>, Integer>(OuterList,
  function(x: IEnumerable<Integer>): IEnumerable<Integer>
  begin
    Result := x;
  end);

ただし、これは少し冗長なので、 anIEnumerable<IEnumerable<T>>を anにフラット化する特殊なケースを処理するメソッドを簡単に作成できIEnumerable<T>ます。

type
  TEnumerableHelper = class helper for TEnumerable
    class function SelectMany<T>(const source: IEnumerable<IEnumerable<T>>): IEnumerable<T>; overload; static;
  end;

class function TEnumerableHelper.SelectMany<T>(
  const source: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
begin
  Result := TSelectManyIterator<IEnumerable<T>, T>.Create(source,
    function(x: IEnumerable<T>): IEnumerable<T>
    begin
      Result := x;
    end);
end;

これを次のように簡単に使用します。

Concated := TEnumerable.SelectMany<Integer>(OuterList);

SelectMany 操作は遅延実行され、遅延評価されます。

于 2016-08-03T12:05:33.473 に答える
1

厳密な (= 非遅延) バージョンは次のようになります。

class function TForm1.Concat<T>(
  const AEnumerable: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
var
  L: IList<T>;
begin
  L := TCollections.CreateList<T>;
  AEnumerable.ForEach(
    procedure(const AInnerEnum: IEnumerable<T>)
    begin
      L.AddRange(AInnerEnum);
    end);
  Result := L as IEnumerable<T>;
end;
于 2016-08-03T11:43:40.723 に答える