如何从multimap中找到所有重复的VALUES <sting,list <string =“”>&gt;?

时间:2016-10-14 04:22:56

标签: c++ duplicates multimap

我正在寻找一种方法来遍历存储在所有键列表中的字符串,并查找所有重复的字符串,删除所有副本,但每个副本中的第一个。 所以,如果我的multimap初始化如下:

 multimap myMap = {
  { "a", { "joe", "greg", jerry", "joe"} }, 
  { "b", { "alan", "joe", "harry"} }
 };  

我想要一个结果:

a= "joe", "greg", "jerry"
b = "alan", "harry"

这是我提出的功能,但它正在抛出“表达式:map / set iterator not dereferencable”。我在下面的代码中评论了抛出错误的行。我很确定这是因为我试图降低无效的end()元素,但不知道如何解决它。有人能指出我为什么这不能正常工作?我没有机会测试这个算法的工作版本,甚至不知道它是否正确(除了明显的异常错误)。

multimap<const string, list<string>> getDuplicates(const map<const string,
                                                   list<string>>& animalsByEnclosure) { 

    multimap<const string, list<string>> duplicates;

    for (auto& enclosure : animalsByEnclosure) {
        list<string> allNames;                                                          
        for (auto& animal : enclosure.second) {
            const string anim = animal;
            int count = 0;
    //problem line follows:
            for (auto& ptr = animalsByEnclosure.end(); ptr->first < enclosure.first; --ptr) {
                for (auto findAnim : ptr->second) {
                    if (animal == findAnim) {
                        if (count > 1) {
                            allNames.insert(allNames.end(), animal);
                            ++count;
                        }
                        else {
                            ++count;
                        }
                        duplicates.insert(pair<const string, list<string>>(enclosure.first, allNames));
                        cout << "Inserting: " << enclosure.first << " and it's doubles:\n";
                        for (auto& c : allNames) {
                            cout << c << endl;
                        }
                    }
                    else {
                        cout << "Animal: " << animal << " not found.\n";
                    }
                }
            }
        }
    }
    return duplicates;
}

2 个答案:

答案 0 :(得分:0)

如果要以相反的顺序遍历STL容器,则应使用rbegin()和rend()。例如。而不是写作

for (auto& ptr = animalsByEnclosure.end();
    ptr->first < enclosure.first;
    --ptr)

你应该写:

for (auto ptr = animalsByEnclosure.rbegin();
    ptr != animalsByEnclosure.rend() && ptr->first < enclosure.first;
    ++ptr)

答案 1 :(得分:0)

首先,如果您使用多图,请正确使用它。 value元素不需要std::list<std::string>,只需std::string即可。

现在,要实现您想要的效果,您可以在迭代地图时维护一组已经遇到的值。如果正在检查的值在该集合中,则表示您刚刚找到重复项并且您想要删除它。您可以在模板函数中收集它:

template <typename K, typename V, typename ... O>
void remove_duplicates(std::multimap<K, V, O...>& map) {
    std::unordered_set<V> values_set;
    for (auto it = map.begin(); it != map.end();) {
        // If we already met the value, we must remove it from the map
        if (values_set.find(it->second) != values_set.end()) {
            it = map.erase(it);
        // Else we register it for potential future encounters and move along
        } else {
            values_set.emplace(it->second);
            ++it;
        }
    }
}

您会找到live demo