dimanche 22 janvier 2017

Can you safely use a std::set as the key to a std::map?

I have defined the following:

typedef std::set<std::string> entry;
typedef std::map<entry, size_t> freq_map;

In this way, I can read in lines from a text file of this form and keep track of each sets frequency:

A;B;C
C;B;A
A;B

In my first scenario I am to create a frequency map of only cardinality one sets

void Apriori::populate_length_one_freq() {
    freq_map length_one_map;
    for (const auto& s : some_data_structure) {
        entry tmp = { s };
        add_to_map(tmp, length_one_map, 1);
    }
    prune_map(length_one_map, 700);
    freq.push_back(length_one_map);
}

void Apriori::add_to_map(entry& en, freq_map& map, size_t ct) {
    auto search = map.find(en);
    if (search != map.end()) {
        map.at(en) += ct;
    } else {
        map.emplace(en, ct);
    }   
}

void Apriori::prune_map(freq_map& m, const size_t cut) {
    for (auto& item : m) {
        if (item.second < cut) {
            m.erase(item.first);
        }
    }
}

This almost works. I am running into an odd bug, however. Certain items do not seem to be getting iterated over in the prune_map function. I can verify this by printing each value to std out while iterating. For example, the item {"Airports"} is not being printed. Strangely, when I do a m.find() of the Airports item in the function, the item is found. See below code:

void Apriori::prune_map(freq_map& m, const size_t cut) {
    std::set<std::string> f = {"Airports"};
    if (m.find(f) != m.end()) {
        std::cout << "found." << std::endl;
    }

    for (auto& item : m) {
        for (auto& s : item.first) {
            std::cout << s << std::endl;
        }
        if (item.second < cut) {
            m.erase(item.first);
        }
    }
}

What could cause my iteration to fail?

Aucun commentaire:

Enregistrer un commentaire