C++ 在c++;stl映射,删除具有重复值的条目

C++ 在c++;stl映射,删除具有重复值的条目,c++,dictionary,stl,C++,Dictionary,Stl,假设map mymap有条目 <'a', 111> <'b', 567> <'c', 956> <'d', 222> <'e', 111> <'f', 222> <'h', 222> <'i', 492> 等等…… 如何删除映射中重复值的条目。 e、 g.键“a”和“e”的值为111。因此,保留“a”的地图条目并删除“e”的条目 对于值222,保留条目“d”并删除条

假设map mymap有条目

<'a', 111>  
<'b', 567>  
<'c', 956>  
<'d', 222>  
<'e', 111>  
<'f', 222>  
<'h', 222>  
<'i', 492> 

等等……
如何删除映射中重复值的条目。

e、 g.键“a”和“e”的值为111。因此,保留“a”的地图条目并删除“e”的条目
对于值222,保留条目“d”并删除条目“f”和“h”。

我正在寻找空间和时间复杂度尽可能高的解决方案

您可能需要这样的解决方案:

#include <iostream>
#include <map>
#include <set>

int main() {
  std::map<char, int> mymap
  {
    {'a', 111}, {'b', 567}, {'c', 956}, {'d', 222}, 
    {'e', 111}, {'f', 222}, {'h', 222}, {'i', 492},
  };

  std::set<int> existingvalues;

  for (auto it = mymap.begin(); it != mymap.end(); it++)
  {
    if (existingvalues.find(it->second) != existingvalues.end())
      mymap.erase(it--);                  // value already encountered => remove entry
    else
      existingvalues.insert(it->second);  // value not yet encountered => remeber it
  }

  for (auto it = mymap.begin(); it != mymap.end(); it++)
    std::cout << "<'" << it->first << "', " << it->second << ">\n";
}
#包括
#包括
#包括
int main(){
std::map mymap
{
{'a',111},{'b',567},{'c',956},{'d',222},
{'e',111},{'f',222},{'h',222},{'i',492},
};
std::设置现有值;
for(auto it=mymap.begin();it!=mymap.end();it++)
{
if(existingvalues.find(it->second)!=existingvalues.end()
mymap.erase(它--);//已遇到值=>删除条目
其他的
existingvalues.insert(it->second);//尚未遇到的值=>记住它
}
for(auto it=mymap.begin();it!=mymap.end();it++)

std::cout您可能想要这样的东西:

#include <iostream>
#include <map>
#include <set>

int main() {
  std::map<char, int> mymap
  {
    {'a', 111}, {'b', 567}, {'c', 956}, {'d', 222}, 
    {'e', 111}, {'f', 222}, {'h', 222}, {'i', 492},
  };

  std::set<int> existingvalues;

  for (auto it = mymap.begin(); it != mymap.end(); it++)
  {
    if (existingvalues.find(it->second) != existingvalues.end())
      mymap.erase(it--);                  // value already encountered => remove entry
    else
      existingvalues.insert(it->second);  // value not yet encountered => remeber it
  }

  for (auto it = mymap.begin(); it != mymap.end(); it++)
    std::cout << "<'" << it->first << "', " << it->second << ">\n";
}
#包括
#包括
#包括
int main(){
std::map mymap
{
{'a',111},{'b',567},{'c',956},{'d',222},
{'e',111},{'f',222},{'h',222},{'i',492},
};
std::设置现有值;
for(auto it=mymap.begin();it!=mymap.end();it++)
{
if(existingvalues.find(it->second)!=existingvalues.end()
mymap.erase(它--);//已遇到值=>删除条目
其他的
existingvalues.insert(it->second);//尚未遇到的值=>记住它
}
for(auto it=mymap.begin();it!=mymap.end();it++)

这是一个有趣的问题,如果有点离题的话

由于映射的值是可散列且相等可比的,因此我们可以在线性时间内执行此操作,使用
无序集
确定之前是否见过该值:

这段代码是c++17:

void comb(std::map<char, int>& themap)
{
    std::unordered_set<int> seen;
    seen.reserve(themap.size());

    // iterate through the map in key order...
    auto current = begin(themap);
    const auto last = end(themap);
    while(current != last)
    {
        auto&&[key, value] = *current;

        // try to insert the value into the 'seen' set.
        if (seen.insert(value).second)
            // if we succeeded, then we're the first ocurrence of the
            // value so move to next node
            ++current;
        else
            // otherwise, erase this node and move to the next
            // (idiomatic method)
            current = themap.erase(current);
    }
}
void梳(标准::映射和主题映射)
{
std::看到无序的_集;
seen.reserve(themap.size());
//按键顺序遍历映射。。。
自动电流=开始(themap);
const auto last=结束(themap);
while(当前!=上次)
{
自动&&[键,值]=*当前;
//尝试将值插入“已看到”集合。
如果(见。插入(值)。秒)
//如果我们成功了,那么我们就是第一个出现这种情况的人
//值,以便移动到下一个节点
++电流;
其他的
//否则,请删除此节点并移动到下一个节点
//(惯用方法)
当前=映射擦除(当前);
}
}

这是一个有趣的问题,虽然有点离题

由于映射的值是可散列且相等可比的,因此我们可以在线性时间内执行此操作,使用
无序集
确定之前是否见过该值:

这段代码是c++17:

void comb(std::map<char, int>& themap)
{
    std::unordered_set<int> seen;
    seen.reserve(themap.size());

    // iterate through the map in key order...
    auto current = begin(themap);
    const auto last = end(themap);
    while(current != last)
    {
        auto&&[key, value] = *current;

        // try to insert the value into the 'seen' set.
        if (seen.insert(value).second)
            // if we succeeded, then we're the first ocurrence of the
            // value so move to next node
            ++current;
        else
            // otherwise, erase this node and move to the next
            // (idiomatic method)
            current = themap.erase(current);
    }
}
void梳(标准::映射和主题映射)
{
std::看到无序的_集;
seen.reserve(themap.size());
//按键顺序遍历映射。。。
自动电流=开始(themap);
const auto last=结束(themap);
while(当前!=上次)
{
自动&&[键,值]=*当前;
//尝试将值插入“已看到”集合。
如果(见。插入(值)。秒)
//如果我们成功了,那么我们就是第一个出现这种情况的人
//值,以便移动到下一个节点
++电流;
其他的
//否则,请删除此节点并移动到下一个节点
//(惯用方法)
当前=映射擦除(当前);
}
}

这里是另一个可能的解决方案,它涉及到在映射容器中迭代2次,如果存在重复值,则第二次迭代的元素将更少:

#include <iostream> 
#include <algorithm>
#include <map>

template <typename T, typename U>
void RemoveDuplicateValues(std::map<T, U> &m)
{
    std::map<U, T> tmp;
    std::for_each(m.rbegin(), m.rend(), [&tmp](auto const &p)
    {
        tmp[p.second] = p.first;
    });

    m.clear();
    for (auto const &p : tmp)
        m[p.second] = p.first;
}

int main()
{
    std::map<char, int> m
    {
        { 'a', 111 },{ 'b', 567 },{ 'c', 956 },{ 'd', 222 },
        { 'e', 111 },{ 'f', 222 },{ 'h', 222 },{ 'i', 492 }
    };

    RemoveDuplicateValues(m);

    // test
    for (auto const &p : m)
        std::cout << p.first << " " << p.second << std::endl;

    return 0;
}

下面是另一个可能的解决方案,它涉及到在映射容器中迭代2次,如果存在重复的值,则第二次迭代的元素将更少:

#include <iostream> 
#include <algorithm>
#include <map>

template <typename T, typename U>
void RemoveDuplicateValues(std::map<T, U> &m)
{
    std::map<U, T> tmp;
    std::for_each(m.rbegin(), m.rend(), [&tmp](auto const &p)
    {
        tmp[p.second] = p.first;
    });

    m.clear();
    for (auto const &p : tmp)
        m[p.second] = p.first;
}

int main()
{
    std::map<char, int> m
    {
        { 'a', 111 },{ 'b', 567 },{ 'c', 956 },{ 'd', 222 },
        { 'e', 111 },{ 'f', 222 },{ 'h', 222 },{ 'i', 492 }
    };

    RemoveDuplicateValues(m);

    // test
    for (auto const &p : m)
        std::cout << p.first << " " << p.second << std::endl;

    return 0;
}

我投票结束这个问题,因为SO不是一个代码编写服务。请显示您的努力构造一组值,如果该值已经在集合中,请从地图中删除该条目。~10-12行代码。“所以保留“a”的地图条目,删除“e”的条目”--为什么?为什么不保留“e”的映射条目并删除“a”的映射条目?您想要的规则也需要成为您问题的一部分。@hvd我想他想保留具有最低键的条目,但您是对的,这应该在question@MichaelWalz“最低”在ASCII中,也需要在以下问题中解释:在大多数C++实现中,代码< > b '< a '/c> >,但这可能是或不可能是OP。我投票将这个问题关闭为非主题,因为这不是一个代码编写服务。请显示您的努力构建一组值,如果值是已在集合中,请从地图中删除条目。~10-12行代码。“因此,保留“a”的地图条目,删除“e”的条目”--为什么?为什么不保留“e”的映射条目并删除“a”的映射条目?您想要的规则也需要成为您问题的一部分。@hvd我想他想保留具有最低键的条目,但您是对的,这应该在question@MichaelWalz“最低”也不太明确,所以需要在ASCII中解释:),在大多数C++实现中,<代码> b’< a ' /COD>,但这可能对OP.来说是不可取的,也可能不是。