ジェネリクス機能を使ったTListを無名メソッドでソートするには

ども、Norimakiです。

今回は無名メソッドでのソートについてです。
毎回、ハマるので記事にしてみました。

通常はTList<T>でデータを格納しておいて、
必要に応じてソートすると。

そういう状況を想定しています。

基本的にソースはこんな感じ。

RtはTList<integer>です。

ちなみに、RtがTList<TMyRecord>なら、

になります。

 
で、結論から言うと無名メソッドの引数、Item1・Item2は、
Rtに格納されている値です。

Rtのインデックスではありません。

まぁ普通は間違わないんでしょうけど、
僕はいつも勘違いしてしまうわけですよ。
格納している値がIntegerですし。

なので、比較する際にも、Item1・Item2が
Rtのインデックスと勘違いして、

Result:=Rt[Item1]-Rt[Item2];

みたいに書いちゃうわけです。でも実際は、

Result:=Item1-Item2;

が正解。

ここでは、TListがIntegerを格納しているから勘違いするわけで、
レコードとかを格納していると、間違わないんですけどね。
まぁ、言い訳です。

さて、

僕が間違える原因のもう一つとして挙げられるのが、僕は普段、
インデックスをリスト化している。ということがあります。

どういうことかというと、

まず、必要なデータをレコード型で定義しておいて、
それをTList<T>に格納すると。

そのデータをフィルタリングしたりソートしたりする際に、
実体をソートするのではなく別途インデックスのリストを用意して、
そちらを操作するということです。

 
たとえば、データの実体を格納するのに、

TList<TNYxxxxx>

というTListを用意したとします。

レコード(TNYxxxxx)の内容としては、名前(Name)と年齢(age)の
2つのデータを保持するとします。

そのリストはこんな感じとします。

(佐藤一郎,15歳)
(斎藤次郎,20歳)
(工藤三郎,37歳)
(灰原史郎,25歳)
(野比五郎,41歳)
(剛田六郎,31歳)
(毛利七郎,75歳)
(武田八郎,74歳)
(細川九郎,55歳)
(加藤十朗,34歳)

で、インデックスをリスト化するとは、別途リスト(TList<integer>)を用意して
フィルタリングをする際に上記データをインデックスで保持するということです。

実際にデータが必要になった場合は、まずリスト(TList<integer>)からインデックスを取得して、
その後実体(TList<TNYxxxxx>)をインデックスで参照すると。そういう方法をとります。

分かりにくいので、具体例を。
上記のデータは上からインデックスを付けると

(佐藤一郎,15歳)がインデックス0(TList<TNYxxxxx>[0])。
(斎藤次郎,20歳)がインデックス1(TList<TNYxxxxx>[1])。

以下同様に、

(加藤十朗,34歳)がインデックス9(TList<TNYxxxxx>[9])。

ということになります。

で、例として、「田」という文字を名前に含む人をフィルタリングするとします。
すると、

(剛田六郎,31歳)...インデックス5(TList<TNYxxxxx>[5])。
(武田八郎,74歳)...インデックス7(TList<TNYxxxxx>[7])。

が、フィルタリングした結果です。

なので、インデックスのリストはこんな感じになります。(TList<integer>)
(もちろん、TList<integer>の数(count)は2)

5 .... インデックス0(TList<integer>[0])
7 .... インデックス1(TList<integer>[1])

さて、ここからが本題。年齢をもとにソートをします。
当然、ソート対象はインデックスのリスト(TList<integer>)です。

まずは、正解から。

こんな感じになるでしょうか。

僕がよくやる間違いは、

とやってしまうことです。

FBodyListが実体のリスト、TList<TNYxxxxx>で
FIndexListがインデックスのリスト、TList<integer>になります。

一番先にも書いた通り、
無名メソッドでの引数、Item1・Item2はTListに格納されている値です。

つまり、
Item1 は FIndexList[Index1] であり、
Item2 は FIndexList[Index2] であるということ。
(Index1・Index2はFIndexListにおけるItem1,Item2のインデックス)

上記のサンプルで言うと、Item1、Item2は5とか7であり、
01ではないということです。

ここら辺をいつも勘違いするので記事にしておきました。
まぁ、備忘録ということで。

 
※表記上、TList<integer>[0]みたいに変な記述がありますが、
 通常はXXX:=TList<integer>.Create;などとインスタンスを生成して
 XXX[0]というように書くのが正解。

 TList<integer>[0]の方が区別しやすいかなと思って
 こっちの書き方にしました。

ではでは。
Norimakiでした。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする