2.12.4. 連想配列#

C/C++ の連想配列クラス map は、Python のディクショナリーや Perl のハッシュと似た機能を持ち、キーと値を 1 セットとしてデータを保存できます。ただし、ディクショナリーやハッシュとの違いとして、map は二分木とよばれるツリー構造で管理されています。そのため、キーと値だけでなく、枝分かれの情報も内部で保持しています。この構造により、map は各要素のキーと値に加えて、順序関係も保持しているという特徴があります。

2.12.4.1. map クラスの#

map クラスは、std::map<std::string, int> のように、キーと値の型を指定して宣言します。一度作成した map クラスの変数には、[] を使ってキーと値を格納できます。

#include <iostream>
#include <string>
#include <map>

int main(void) {
    std::map<std::string, int> seqLen;

    seqLen["CGAGT"] = 5;
    seqLen["TT"] = 2;
    seqLen["CGATCGTGTC"] = 10;

    std::cout << seqLen["TT"] << std::endl;
    // 2
    
    return 0;
}

map クラスに格納されたすべての要素を順に処理するには、いくつかの方法があります。例えば、イテレーターを利用して値を取得したり、C++17 以降であれば構造化束縛を利用してキーと値を直接受け取ったりすることができます。

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<std::string, int> seqLen = {
        {"CGAGT", 5},
        {"TT", 2},
        {"CGATCGTGTC", 10}
    };

    // example 1: iterator
    for (auto i = seqLen.begin(); i != seqLen.end(); ++i) {
        std::cout << i->first << " => " << i->second << std::endl;
    }

    // example 2: C++17 structured bindings
    for (const auto& [seq, len] : seqLen) {
        std::cout << seq << " => " << len << std::endl;
    }

    return 0;
}

2.12.4.2. キーの検索#

キーの検索には find 関数を利用します。指定したキーが存在する場合は、その要素を指すイテレーターが返され、存在しない場合は end() が返されます。

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<std::string, int> seqLen = {
        {"CGAGT", 5},
        {"TT", 2},
        {"CGATCGTGTC", 10}
    };

    auto itr = seqLen.find("AA");

    if (itr != seqLen.end()) {
        std::cout << "key found." << std::endl;
    } else {
        std::cout << "key NOT found." << std::endl;
    }

    return 0;
}

2.12.4.3. キーの削除#

std::map から要素を削除するには erase 関数を使用します。削除したいキーが存在しない場合に備えて、事前に find で確認してから削除するのが安全な使い方です。

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<std::string, int> seqLen = {
        {"CGAGT", 5},
        {"TT", 2},
        {"CGATCGTGTC", 10}
    };

    auto itr = seqLen.find("TT");
    if (itr != seqLen.end()) {
        seqLen.erase(itr);
    }

    return 0;
}

2.12.4.4. メンバー関数#

std::map には、状態を確認したり中身を操作したりするための便利なメンバー関数が用意されています。

  • size は、map クラスのオブジェクトに含まれる要素数を返します。

  • empty は、オブジェクトが空かどうかを調べる関数です。空であれば true、要素が存在する場合は false を返します。

  • clear は、オブジェクトに含まれるすべての要素を削除します。一気に片付けたいときに便利です。

#include <iostream>
#include <string>
#include <map>

int main() {
    std::map<std::string, int> seqLen = {
        {"CGAGT", 5},
        {"TT", 2},
        {"CGATCGTGTC", 10}
    };

    std::cout << seqLen.size() << std::endl;   // 3
    std::cout << seqLen.empty() << std::endl;  // 0 (false)

    seqLen.clear();

    std::cout << seqLen.size() << std::endl;   // 0
    std::cout << seqLen.empty() << std::endl;  // 1 (true)

    return 0;
}