導入
表の中から「特定の条件に合う要素」を探したいとき、PERFORMでループを回しながらIFで調べる方法もありますが、COBOLには表探索専用の SEARCH文 が用意されています。
説明
SEARCH(線形探索) は、表の先頭から1つずつ順番に調べていきます。
01 WS-NAMES.
05 WS-NAME PIC X(10) OCCURS 5 TIMES
INDEXED BY WS-NAME-IDX.
01 WS-FOUND-FLAG PIC X(1) VALUE "N".
PROCEDURE DIVISION.
*> (事前に WS-NAME(1)〜WS-NAME(5) に名前を入れてある想定)
SEARCH WS-NAME
AT END
DISPLAY "見つかりませんでした"
WHEN WS-NAME(WS-NAME-IDX) = "SUZUKI"
MOVE "Y" TO WS-FOUND-FLAG
DISPLAY "見つかりました: " WS-NAME-IDX
END-SEARCH.
SEARCH WS-NAME…INDEXED BYで宣言したインデックス(WS-NAME-IDX)を使って、WS-NAMEの表を先頭から調べる。WHEN 条件… 条件に一致した時点で探索を終了し、その節の処理を実行する。このときWS-NAME-IDXには見つかった位置が入っている。AT END… 表の最後まで調べても見つからなかった場合の処理。
SEARCH ALL(二分探索) は、表があらかじめキー順に並んでいることが前提の、より高速な探索方法です。
01 WS-CODES.
05 WS-CODE PIC 9(4) OCCURS 100 TIMES
ASCENDING KEY IS WS-CODE
INDEXED BY WS-CODE-IDX.
PROCEDURE DIVISION.
SEARCH ALL WS-CODE
AT END
DISPLAY "コードが見つかりません"
WHEN WS-CODE(WS-CODE-IDX) = 1050
DISPLAY "見つかった位置: " WS-CODE-IDX
END-SEARCH.
ASCENDING KEY IS WS-CODE… 表があらかじめ昇順(小さい順)に並んでいることを宣言する。これがSEARCH ALLを使うための前提条件です。SEARCH ALLは、100件の表なら最悪でも約7回程度の比較で見つけられる二分探索のアルゴリズムを、コンパイラが自動で実装してくれます。線形探索のSEARCH(最悪100回の比較)より効率的です。
表が小さいうちは SEARCH で十分ですが、数百〜数千件規模の表を何度も検索するような処理では SEARCH ALL(二分探索)が効果を発揮します。ただし表を事前にソートしておく必要がある点を忘れないようにしましょう。
試すには
レッスン30で作った5人分の点数表に名前を追加し、SEARCH で「名前が”YAMADA”の人の点数」を探すコードを書いてみましょう。見つかった位置のインデックスを使って、対応する点数もあわせてDISPLAYしてみてください。