如何将 IEnumerable 的 IEnumerable 折叠为单个 IEnumerable?
How to collapse an IEnumerable of an IEnumerable to a single IEnumerable?
function TSomething.Concat<T>(const E: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
begin
Result := TConcatIterator<T>.Create(E) as IEnumerable<T>;
end;
那不编译,因为 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 中实现它?
严格(=非惰性)版本可能如下所示:
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;
由于 Spring4D 集合是根据 .Net 中的集合建模的,因此您要查找的 operation/method 称为 SelectMany。
在 1.2 中,我们在 TEnumerable
类型中有一个静态方法,因此代码如下所示:
Concated := TEnumerable.SelectMany<IEnumerable<Integer>, Integer>(OuterList,
function(x: IEnumerable<Integer>): IEnumerable<Integer>
begin
Result := x;
end);
但是这有点冗长,因此您可以轻松编写一个方法来处理将 IEnumerable<IEnumerable<T>>
展平为 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 操作被延迟执行并延迟计算。
function TSomething.Concat<T>(const E: IEnumerable<IEnumerable<T>>): IEnumerable<T>;
begin
Result := TConcatIterator<T>.Create(E) as IEnumerable<T>;
end;
那不编译,因为 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 中实现它?
严格(=非惰性)版本可能如下所示:
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;
由于 Spring4D 集合是根据 .Net 中的集合建模的,因此您要查找的 operation/method 称为 SelectMany。
在 1.2 中,我们在 TEnumerable
类型中有一个静态方法,因此代码如下所示:
Concated := TEnumerable.SelectMany<IEnumerable<Integer>, Integer>(OuterList,
function(x: IEnumerable<Integer>): IEnumerable<Integer>
begin
Result := x;
end);
但是这有点冗长,因此您可以轻松编写一个方法来处理将 IEnumerable<IEnumerable<T>>
展平为 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 操作被延迟执行并延迟计算。