【问题标题】:Find set_difference between set and map keys查找集合和映射键之间的 set_difference
【发布时间】:2013-03-12 20:34:45
【问题描述】:

我想问是否可以提供一个示例,说明如何使用 set_difference 找到地图的集合和键之间的差异

我知道另一个问题std::set_difference is it possible to compare set and map Keys?,但它指向另一个没有明确示例的问题。我需要一个不使用 boost 库的解决方案

#include <algorithm>
#include <set>
#include <iterator>
// ...
std::set<int> s1, s2;
// Fill in s1 and s2 with values
std::set<int> result;
std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
    std::inserter(result, result.end()));

【问题讨论】:

  • 我在这里没有看到任何map
  • @jrok 请再次阅读问题。H2CO3 对此感到抱歉。
  • 它说 “我想问一下是否可以提供一个例子来说明我如何找到 setkeys 之间的区别一张地图。你展示的代码计算了两组之间的差异。那么,你介意举个例子来说明你所说的吗?
  • @jrok 我想找出一组和地图键之间的区别。

标签: c++ map set set-difference


【解决方案1】:

您可以使用自定义比较器来做到这一点。标准算法使用严格的弱排序。要测试两个元素是否相等,需要应用两次比较器。当comp(first, second)comp(second, first) 返回false 时,两个元素相等(其中comp 是比较器函数)。由于您要比较的元素是不同类型的,所以一个比较器是不行的 - 您需要两个重载:

struct cmp {
    bool operator()(int i, const std::pair<int, double>& p) const
    {
        return i < p.first;
    }

    bool operator()(const std::pair<int, double>& p, int i) const
    {
        return p.first < i;
    }

};

int main()
{

    std::set<int> s1 { 1, 2, 3, 4 };
    std::map<int, double> s2 { {1, 0}, {2,0}, {4,0} };

    std::set<int> result;

    std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(),
        std::inserter(result, result.end()), cmp());

    std::cout << *result.begin(); // will print 3

}

【讨论】:

  • 没问题。不过,老实说,我会使用 boost::transform_iterator 和一个简单的比较器作为 lambda 传递。
  • 是的,我知道,但我没有安装 boost 库,我想要一个自定义解决方案。顺便说一句,是否可以为字符串(字符串集和映射键作为字符串)提供等效示例?提前致谢。
  • 抱歉,您的解决方案不能使用 MS Visual Studio Express 2013 构建:错误 C2664: 'bool cmp::operator ()(int,const std::pair &) const ' : 无法将参数 2 从 'std::pair' 转换为 'int' 错误 C2664: 'bool cmp::operator ()(int,const std::pair &) const ' : 无法将参数 1 从 'const int' 转换为 'const std::pair &'
  • @Superlokkus 你确定你在比较器中有两个operator() 重载吗?错误消息看起来好像缺少一个。
  • @jrok 是的,我只是从答案中复制了整个代码并添加了标题
【解决方案2】:

@Superlokkus @jrok 我知道这篇文章晚了大约一年......仍然希望澄清这个问题。 当比较运算符重载时,MS Visual Studio 会出现问题。问题是有两种组合没有被考虑在内:

struct cmp {
    bool operator()(const int& i, const std::pair<int, double>& p) const
    {
        return i < p.first;
    }
    bool operator()(const std::pair<int, double>& p, const int& i) const
    {
        return p.first < i;
    }
    bool operator()(const std::pair<int, double>& p1,
        const std::pair<int, double>& p2) const
    {
        return p1.first < p2.first;
    }
    bool operator()(const int& i1, const int& i2) const
    {
        return i1 < i2;
    }
};

通过插入最后两个运算符,我们插入了编译器获得差异所需的所有选项。事实上,我建议使用const int&amp; 而不是像前两个运算符中介绍的那样简单地使用int。对于小情况,这无关紧要,但是当我们有非常大的对数组、整数数组,或者更糟糕的是,非常大的容器时,操作将受到内存限制,因为我们将有很多内存访问。通过使用它,我们传递参数的引用并且不需要复制参数,因此避免了复制操作并用另一组完全不必要的值填充缓存。

最后一点,我发现@jrok 提出的第一个解决方案在发布模式(MSVC 2013)下完美编译,而不是在调试中,这很奇怪。很高兴知道为什么!

【讨论】:

    【解决方案3】:

    我自己对如何编写比较谓词的轻微偏好是:

    class KeyLess
    {
        public:
    
          template< typename KeyType >
          static KeyType getKey( const KeyType& k ) 
          {  
              return k;
          }
    
          template< typename KeyType, typename ValueType >
          static KeyType getKey( std::pair< const KeyType, ValueType > const& p ) 
          {         
              return p.first;
          }
    
          template< typename L, typename R >
          bool operator()( const L& l, const R& r ) const
          {
              return getKey( l ) < getKey( r );
          }
    };
    

    您现在可以在整个代码中使用它。

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 2021-12-23
      • 2010-11-23
      • 2015-02-12
      • 1970-01-01
      • 2018-05-08
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多