delphi-collはジェネリックを用いたコレクションのクラスライブラリです。
標準ライブラリのGenerics.Collectionsにはない便利な機能が追加されています。
delphi-collのCollections.Lists.TList<T>を使ってみました。
■Aggregateメソッド
Aggregateメソッドは要素に対して順番に引数の関数を実行して、結果を返します。
最初に先頭の要素と次の要素を引数にして関数を実行します。
2回目以降のループでは、前の関数の実行結果と次の要素を引数にして関数を実行します。
最後の要素まで繰り返し、最後の値を返します。
次のコードはリストの要素の合計値を出力します。
uses
Collections.Lists
var
NumList: TList<Integer>;
Total: Integer;
begin
NumList := TList<Integer>.Create();
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
NumList.Add(3);
Total := NumList.Aggregate(
function(Sum, Val: Integer): Integer
begin
Exit(Sum + Val)
end
);
WriteLn(Total); //=> 10
■Allメソッド、Anyメソッド
Allメソッドは、要素に対して引数の関数を実行し、すべての要素がTrueの場合にTrueを返します。
1つでもFalseの要素があればFalseを返します。
Anyメソッドは、要素に対して引数の関数を実行し、すべての要素がFalseの場合にFalseを返します。
1つでもTrueの要素があればTrueを返します。
次のコードはリストが条件を満たす時は’OK’と出力します。
var
NumList: TList<Integer>;
begin
NumList := TList<Integer>.Create();
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
NumList.Add(3);
//すべての要素が0より大きいか
if NumList.All(
function(Val: Integer): Boolean begin Exit(Val > 0); end) then
begin
WriteLn('OK');
end;
//3より大きい要素があるか
if NumList.Any(
function(Val: Integer): Boolean begin Exit(Val > 3); end) then
begin
WriteLn('OK');
end;
■Minメソッド、Maxメソッド
Minメソッドは比較関数で比較して最も値が小さい要素を返します。
Maxメソッドは比較関数で比較して最も値が大きい要素を返します。
比較関数はリストのコンストラクタで指定します。
次のコードは人物リストの中から生年月日の最も新しい人物と最も古い人物を出力します。
type
TPerson = record
FName: string;
FBirthDate: TDate;
constructor Create(const AName: string; const ABirthDate: TDate);
end;
//生年月日で比較する比較関数
TPersonAgeComparer = class(TCustomComparer<TPerson>)
public
function Compare(const Left, Right: TPerson): Integer; override;
function Equals(const Left, Right: TPerson): Boolean; override;
function GetHashCode(const Value: TPerson): Integer; override;
end;
constructor TPerson.Create(const AName: string; const ABirthDate: TDate);
begin
FName := AName;
FBirthDate := ABirthDate;
end;
function TPersonAgeComparer.Compare(const Left, Right: TPerson): Integer;
begin
Result := DateUtils.CompareDate(Left.FBirthDate, Right.FBirthDate);
end;
function TPersonAgeComparer.Equals(const Left, Right: TPerson): Boolean;
begin
Result := DateUtils.SameDate(Left.FBirthDate, Right.FBirthDate);
end;
function TPersonAgeComparer.GetHashCode(const Value: TPerson): Integer;
begin
Result := Trunc(Value.FBirthDate);
end;
procedure Main;
var
PersonList: TList<TPerson>;
Comparer: TPersonAgeComparer;
Person: TPerson;
begin
Comparer := TPersonAgeComparer.Create;
PersonList := TList<TPerson>.Create(TRules<TPerson>.Custom(Comparer));
PersonList.Add(TPerson.Create('John', EncodeDate(1984, 1, 4)));
PersonList.Add(TPerson.Create('Mary', EncodeDate(1955, 4, 11)));
PersonList.Add(TPerson.Create('Ken', EncodeDate(2001, 8, 23)));
PersonList.Add(TPerson.Create('Lidia',EncodeDate(1978, 3, 10)));
//生年月日が最も新しい人物
Person := PersonList.Max;
WriteLn(Person.FName, ' ', DateToStr(Person.FBirthDate));
//=> Ken 2001/08/23
//生年月日が最も古い人物
Person := PersonList.Min;
WriteLn(Person.FName, ' ', DateToStr(Person.FBirthDate));
//=> Mary 1955/04/11
■FirstWhereメソッド、FirstWhereNotメソッド
FirstWhereメソッドは条件に該当する最初の要素を返します。
FirstWhereNotメソッドは条件に該当しない最初の要素を返します。
次のコードはリストの中から生年月日が2000年以降である最初の人物と生年月日が2000年以降でない最初の人物を取得します。
var
PersonList: TList<TPerson>;
Person: TPerson;
begin
PersonList := TList<TPerson>.Create;
PersonList.Add(TPerson.Create('John', EncodeDate(1984, 1, 4)));
PersonList.Add(TPerson.Create('Mary', EncodeDate(1955, 4, 11)));
PersonList.Add(TPerson.Create('Ken', EncodeDate(2001, 8, 23)));
PersonList.Add(TPerson.Create('Lidia',EncodeDate(1978, 3, 10)));
//生年月日が2000年以降である最初の人物
Person := PersonList.FirstWhere(
function(P: TPerson):Boolean begin
Exit(CompareDate(EncodeDate(2000, 1, 1), P.FBirthDate) = LessThanValue)
end);
WriteLn(Person.FName, ' ', DateToStr(Person.FBirthDate));
//=> Ken 2001/08/23
//生年月日が2000年以降でない最初の人物
Person := PersonList.FirstWhereNot(
function(P: TPerson):Boolean begin
Exit(CompareDate(EncodeDate(2000, 1, 1), P.FBirthDate) = LessThanValue)
end);
WriteLn(Person.FName, ' ', DateToStr(Person.FBirthDate));
//=> John 1984/01/04
■FirstWhereLowerメソッド、FirstWhereGreaterメソッド、FirstWhereBetweenメソッド
FirstWhereLowerメソッドは引数の値以下の最初の要素を返します。
FirstWhereGreaterメソッドは引数の値以上の最初の要素を返します。
FirstWhereBetweenメソッドは第1引数以上、第2引数以下の最初の要素を返します。
var
NumList: TList<Integer>;
Num: Integer;
begin
NumList := TList<Integer>.Create();
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
NumList.Add(3);
//3以下の最初の要素
Num := NumList.FirstWhereLower(3);
WriteLn(Num); //=> 2
//3以上の最初の要素
Num := NumList.FirstWhereGreater(3);
WriteLn(Num); //=> 4
//3以上4以下
Num := NumList.FirstWhereBetween(3, 4);
WriteLn(Num); //=> 4
■WhereLowerメソッド、WhereGreaterメソッド、WhereBetweenメソッド
WhereLowerメソッドは引数未満の要素を返します。
WhereGreaterメソッドは引数より大きい要素を返します。
WhereBetweenメソッドは引数の間の要素を返します。
var
NumList: TList<Integer>;
Num: Integer;
begin
NumList := TList<Integer>.Create();
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
NumList.Add(3);
//3以下の要素
for Num in NumList.WhereLower(3) do
WriteLn(Num); //=> 2,1
//3以上の要素
for Num in NumList.WhereGreater(3) do
WriteLn(Num); //=> 4
//3以上4以下
for Num in NumList.WhereBetween(2, 4) do
WriteLn(Num); //=> 2,4,3
■Distinctメソッド
Distinctはリストから重複する要素を除いた要素を返します。
var
NumList: TList<Integer>;
Num: Integer;
begin
NumList := TList<Integer>.Create();
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
NumList.Add(3);
NumList.Add(2);
NumList.Add(4);
NumList.Add(1);
for Num in NumList.Distinct do
WriteLn(Num); //=> 2 4 1 3
■Orderedメソッド
Orderedメソッドは、比較関数で並び替えた新しいリストを返します。
var
PersonList: TList<TPerson>;
Person: TPerson;
begin
PersonList := TList<TPerson>.Create;
PersonList.Add(TPerson.Create('John', EncodeDate(1984, 1, 4)));
PersonList.Add(TPerson.Create('Mary', EncodeDate(1955, 4, 11)));
PersonList.Add(TPerson.Create('Ken', EncodeDate(2001, 8, 23)));
PersonList.Add(TPerson.Create('Lidia',EncodeDate(1978, 3, 10)));
for Person in PersonList.Ordered(
function(const Right, Left: TPerson): Integer
begin
Exit(CompareStr(Right.FName, Left.FName));
end) do
WriteLn(Person.FName);
//=> John Ken Lidia Mary
■Concatメソッド
Concatメソッドは引数の要素を結合した新しいリストを返します。
var
List1, List2: TList<Integer>;
Num: Integer;
begin
List1 := TList<Integer>.Create;
List1.Add(1);
List1.Add(5);
List1.Add(3);
List2 := TList<Integer>.Create;
List2.Add(5);
List2.Add(4);
List2.Add(3);
for Num in List1.Concat(List2) do
WriteLn(Num);
//=> 1 5 3 5 4 3
■Unionメソッド
Unionメソッドは重複しない要素を結合した新しいリストを返します。
var
List1, List2: TList<Integer>;
Num: Integer;
begin
List1 := TList<Integer>.Create;
List1.Add(1);
List1.Add(5);
List1.Add(3);
List2 := TList<Integer>.Create;
List2.Add(5);
List2.Add(4);
List2.Add(3);
for Num in List1.Union(List2) do
WriteLn(Num);
//=> 1 5 3 4
■Excludeメソッド
Excludeメソッドは引数に存在しない要素を持つ新しいリストを返します。
var
List1, List2: TList<Integer>;
Num: Integer;
begin
List1 := TList<Integer>.Create;
List1.Add(1);
List1.Add(5);
List1.Add(3);
List2 := TList<Integer>.Create;
List2.Add(5);
List2.Add(4);
List2.Add(3);
for Num in List1.Exclude(List2) do
WriteLn(Num);
//=> 1
■Intersectメソッド
Intersectメソッドは重複する要素を持つ新しいリストを返します。
var
List1, List2: TList<Integer>;
Num: Integer;
begin
List1 := TList<Integer>.Create;
List1.Add(1);
List1.Add(5);
List1.Add(3);
List2 := TList<Integer>.Create;
List2.Add(5);
List2.Add(4);
List2.Add(3);
for Num in List1.Intersect(List2) do
WriteLn(Num);
//=> 5 3
次回「delphi-collを使ってみる(2)」に続きます。
Pingback: delphi-collを使ってみる(2) « 山本隆の開発日誌
Pingback: ページが見つかりませんでした « 山本隆の開発日誌
Pingback: delphi-collを使ってみる(4) C#のクエリメソッドと比較する « 山本隆の開発日誌