TStringListからvector / TStringDynArrayからvector[C++Builder]

C++Builder(およびDelphi)でよく使われるTStringListとかDynamicArrayを、std::vectorに変換したい場合がよくある。
この場合、いちいちループを回さなくても、STLライクなイテレータ操作が使える、ということを今さら公式ヘルプで知ったのでメモ。

TStringListからvector

TStringListからstd::vectorは以下のように一発で変換可能。

既存のvectorにはassignで代入。

スマートポインタでも問題ない。

文字列リストの基底クラスであるTStringsも同様。
おなじみのフォント一覧を取得するケース。

ソートされた結果を最初から得たい場合は、std::setをいきなり初期化してもいい。

 

DynamicArrayからvector

Delphi動的配列型のDynamicArrayも似たような代入が可能。

IOUtilsのTDirectory::GetFilesはディレクトリ内の全ファイルを一発で取れる便利な関数だが、この返値TStringDynArrayDynamicArray<String>のtypedefなので、同様にvector等に変換できる。

 

以上、C++Builder10.2.3 / Windows10(21H2)で確認。

vectorの重複要素をソートせずに削除する[c++]

vectorの重複要素の削除は、まずソートしてから std::unique / erase という定番手法があるが、現在の要素の順番を崩さないまま行いたい場合もある。

こうしたケース用に、何か定番の方法があるのかと調べたら、こちらのサイトを見ただけでも実にいろいろなやり方があるらしい。

とりあえず、要素の大きさとか重複率とか気にせず、速度や効率にこだわらなければ、結局 std::set を使うベタな方法が個人的には一番分かりやすかった。

なおstd::setのメンバ関数countは1か0を返すだけ。std::findを使うよりシンプルに書ける。

テンプレート関数を作っておくと、どんな型を突っ込んだvectorでもだいたい使えるので楽かもしれない。(というか自分用に作った)

ついでに std::remove_if と c++11以降のラムダ式も使ったバージョン。std::deque版。

これは、setのinsert関数の返値を使うともっとシンプルに書ける、とこちらのサイトで知った。

setのメンバ関数 insert は、引数1つのバージョンだと std::pair<iterator,bool>を返す。挿入に成功するとsecondにはtrueが入る。なるほど便利。

   
C++Builder10.2.3で確認。