【问题标题】:In c++ stl map, delete entries with duplicate values [closed]在c ++ stl map中,删除具有重复值的条目[关闭]
【发布时间】:2018-05-16 09:10:32
【问题描述】:

考虑 map mymap 有条目

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

等等……
如何删除地图中重复值的条目。
例如键 'a' 和 'e' 存在值 111。所以保留“a”的地图条目并删除“e”的条目
对于值 222,保留条目“d”并删除条目“f”和“h”。
我正在寻找具有最佳空间和时间复杂度的解决方案

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为 SO 不是代码编写服务。请展示你的努力
  • 构造一组值,如果该值已经在集合中,则从地图中删除该条目。 ~10-12 行代码。
  • "所以保留 'a' 的映射条目并删除 'e' 的条目" -- 为什么?为什么不保留“e”的地图条目并删除“a”的地图条目?您想要的规则也需要成为您问题的一部分。
  • @hvd 我想他想保留最低键的条目,但你是对的,这应该在问题中指定
  • @MichaelWalz "Lowest" 也未指定,因此需要在问题中解释 :) 在 ASCII 中,因此在大多数 C++ 实现中,'B' &lt; 'a',但这对于OP。

标签: c++ dictionary stl


【解决方案1】:

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

因为您的地图的值是可散列的且相等性可比的,所以我们可以在线性时间内执行此操作,使用unordered_set 来确定该值之前是否见过:

这段代码是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);
    }
}

【讨论】:

    【解决方案2】:

    你可能想要这样的东西:

    #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";
    }
    

    【讨论】:

      【解决方案3】:

      这是另一种可能的解决方案,涉及迭代地图容器 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;
      }
      

      演示:https://ideone.com/oThy17

      a 111
      b 567
      c 956
      d 222
      i 492
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-08
        • 2013-05-04
        • 1970-01-01
        • 1970-01-01
        • 2012-09-30
        • 1970-01-01
        • 2018-10-16
        • 2016-11-06
        相关资源
        最近更新 更多