[MQL4] CArrayObj はソート済みじゃないと Search() の結果が -1 になってしまう
MQL4 で可変長配列を使用する方法 で既に書いたのですが、以下のように CArrayObj::Search()
を呼んでも正しくインデックスが返ってこない時があります。
Item
等の定義は MQL4 で可変長配列を使用する方法 を参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | for ( int i = 0; i < 10; i++) { int value = (i % 2 == 0) ? i : i + 10; m_item_array.Add( new Item(value)); } // 途中に挿入 Item* item_100 = new Item(100); m_item_array.Insert(item_100, 5); // 今挿入したばかりのオブジェクトを検索する int index = m_item_array.Search(item_100); printf ( "index: %d" , index); // 結果 // index: -1 |
原因
Include/Arrays/ArrayObj.mqh
中の Search()
の定義を見てみると、m_sort_mode==-1
とあります。
571 572 573 574 575 576 | int CArrayObj::Search( const CObject *element) const { int pos; //--- check if (m_data_total==0 || ! CheckPointer (element) || m_sort_mode==-1) return (-1); |
この m_sort_mode
とは何かというと、基底クラスの中に以下のような実装があります。
ソートが行われると、m_sort_mode
がセットされるというわけです。
79 80 81 82 83 84 | void CArray::Sort( const int mode) { //--- check if (IsSorted(mode)) return ; m_sort_mode=mode; |
つまり、Sort()
を実行していない配列に対しては Search()
は -1
を返すということです。
ちょっと不親切ですね。
対策
上記の通り、Search()
を呼ぶ前に Sort()
を呼べば OK です。
10 11 12 13 14 15 16 | m_item_array.Sort(); int index = m_item_array.Search(item_100); printf ( "index: %d" , index); // 結果 // index: 10 |
なお、Compare()
の実装によっては Sort()
したとしても正しい index が返ってこない場合があります。
注意が必要です。
参考
補足: sort_mode とは
Sort()
の引数として渡される mode
。
以下のようにデフォルト 0
で定義されています。
37 | void Sort( const int mode=0); |
これは何に使われるのでしょうか?
実は、CObject の Compare()
の引数としてそのまま渡されます。
1 | virtual int Compare( const CObject *node, const int mode=0) const ; |
この mode
のについて明確に定義しているドキュメントは見つけることが出来ませんでした。
Compare()
を override した人が自分で決めれば良いようです。
一般的に、0
ならば降順、1
ならば昇順といった感じでしょうか。