如何找到两张地图的区别?

时间:2014-06-18 02:10:43

标签: c++ map

我正在尝试实现与set_intersection和set_difference类似的函数,而是使用map作为我的日期类型进行赋值。我能够找到交叉点,但我的差异函数的输出不是我想要的,我无法弄清楚为什么。我正在使用的两个功能如下。

map<string, int> Group::Intersection(map<string, int> &tempSet, map<string, int> &currentSet){
    map<string, int>::const_iterator input_iterator;
    map<string, int> result;
    typename map<string, int>::const_iterator it1 = tempSet.begin();
    typename map<string, int>::const_iterator it2 = currentSet.begin();

    while (it1 != tempSet.end() && it2 != currentSet.end())
    {
        if (it1->first < it2->first)
            ++it1;
        else if (it2->first < it1->first)
            ++it2;
        else{
            result.insert(make_pair(it2->first, min(it1->second, it2->second)));
            ++it1;
            ++it2;
        }
    }

    return result;
}

map<string, int> Group::Difference(map<string, int> &tempSet, map<string, int> &currentSet){
    map<string, int>::const_iterator input_iterator;
    map<string, int> result;
    typename map<string, int>::const_iterator it1 = tempSet.begin();
    typename map<string, int>::const_iterator it2 = currentSet.begin();

    while (it1 != tempSet.end() && it2 != currentSet.end())
    {
        if (it1->first < it2->first){
            result.insert(make_pair(it1->first, abs(it1->second - it2->second)));
            ++it1;
        }
        else if (it2->first < it1->first){
            result.insert(make_pair(it2->first, abs(it1->second - it2->second)));
            ++it2;
        }
        else{            
            ++it1;
            ++it2;
        }
    }
    return result;
}

使用这两个列表:

cat 5
dog 4
bear 2
dinosaur 1

cat 6
dog 4
snake 3
lion 4

我收到了猫5和狗4的交集,但差别给了我4熊和恐龙3.据我所知,这是从第一张地图中取出两个键并将它们与来自第二张地图,但我无法确定它是我的迭代还是我将键/值放入新地图。任何建议都会非常感激,因为我觉得这应该是一个我无法弄清楚的简单解决方案。

4 个答案:

答案 0 :(得分:2)

您处理错误的最终案例。一旦到达 列表的末尾,就会停止,这会导致您省略条目。 (考虑一个列表为空的琐碎案例。你根本不输出任何东西。)

答案 1 :(得分:2)

您设置差异的问题在于,在完成迭代后,可能会在任一列表中留下元素。所以在你的wile循环之后你需要添加:

while (it1 != tempSet.end()) //add remaining elements from first map
{
  result.insert(*it1++);
}
while (it2 != currentSet.end()) //add remaining elements from second map
{
  result.insert(*it2++);
}

答案 2 :(得分:0)

这是一个答案,也是一种寻求澄清的尝试。

寻求澄清

说你有:

std::map<std::string, int> c1 = {{"a", 10}, {"b", 20}, {"c", 30}, {"d", 40}, {"f", 40}};
std::map<std::string, int> c2 = {{"b", 200}, {"c", 300}, {"d", 400}, {"e", 500}};

std::map<std::string, int> c3 = map_intersect(c1, c2);
std::map<std::string, int> c4 = map_difference(c1, c2);

您期望c3是什么?

{{"b", 20}, {"c", 30}, {"d", 40}}

{{"b", 200}, {"c", 300}, {"d", 400}}

该问题的答案将决定如何实施map_intersect功能。

您期望c4是什么?期望它是更自然的:

{{"a", 10}, {"f", 40}}

有一些假设的解决方案

假设您希望上面c3的值为:

{{"b", 20}, {"c", 30}, {"d", 40}}

以及c4的值为:

{{"a", 10}, {"f", 40}}

以下实现在我的测试中起作用:

std::map<std::string, int> map_intersect(std::map<std::string, int> const& c1,
                                         std::map<std::string, int> const& c2)
{
   std::map<std::string, int> ret;
   std::map<std::string, int>::const_iterator iter = c2.begin();
   std::map<std::string, int>::const_iterator end = c2.end();
   for ( ; iter != end; ++iter )
   {
      if ( c1.find(iter->first) != c1.end() )
      {
         ret[iter->first] = iter->second;
      }
   }

   return ret;
}

std::map<std::string, int> map_difference(std::map<std::string, int> const& c1,
                                          std::map<std::string, int> const& c2)
{
   std::map<std::string, int> ret = c1;
   std::map<std::string, int>::const_iterator iter = c2.begin();
   std::map<std::string, int>::const_iterator end = c2.end();
   for ( ; iter != end; ++iter )
   {
      if ( c1.find(iter->first) != c1.end() )
      {
         ret.erase(iter->first);
      }
   }
   return ret;
}

答案 3 :(得分:0)

你需要定义你想要的操作的预期结果,但是有一些东西有点气味:

    if (it1->first < it2->first){
        result.insert(make_pair(it1->first, abs(it1->second - it2->second)));
        ++it1;
    }

创建由it1->first索引的条目是否有意义,该条目包含通过减去与it1->first相关联的原始值和某些不相关的值而获得的数字?在这种情况下,键不同,可能并不意味着聚合值。

    else{            
        ++it1;
        ++it2;
    }

如果两个地图都包含相同的密钥,您只需忽略它?你应该检查相关的值吗?在这种情况下,合并两个地图的结果实际上是有意义的。除此之外,我不确定你是否想要使用绝对值。在我的书中1 - 55 - 1不同。保持符号可以帮助您在稍后阶段确定两个输入中的哪一个具有更大的键值。

while (it1 != tempSet.end() && it2 != currentSet.end()) {
   …
}

其中一张地图完成后会发生什么?你想忽略其他地图中的值吗?考虑退化情况:具有N个键值对和空映射的地图,应该是什么区别,映射?这就是算法生成的内容。

除了算法本身,我建议您采用一种有条理的方法进行测试。从下到上构建小测试用例:前两个空映射,然后一个空映射,一个值,然后两个一个值相同/不同,相同/不同的值,然后...通过从地面构建测试用例你将有更大的机会挑出算法中的问题。例如,在一个映射中有一个元素而在另一个映射中没有一个(两个方向)的测试用例会让你考虑循环中的终止条件。如果匹配键存在问题,则具有相同键和相同/不同值的两个集合将暗示。等等。