【问题标题】:How to avoid duplicate pairs / find a pair in multimap?如何避免重复对/在多图中找到一对?
【发布时间】:2012-09-11 04:22:55
【问题描述】:

我有一些(工作)代码使用multimap<string,string>。我想更改它以禁止同一键上的重复值(显然同一键上的不同值很好,否则我不会使用多重映射)。

令人惊讶的是,该类型并没有seem 有一个内置的方法来避免重复,也没有找到键值对(只找到一个键)。但我认为 SO 上的某个人必须有现成的解决方法。有人吗?

【问题讨论】:

  • 是否允许具有不同键的重复值?您希望多次使用多少个键,并且使用频率如何?
  • 当然,不同键上的相同值是可以的。在我的情况下,扇出很小(通常每个键 1 或 2 个值),因此 DeadMG 切换到 std::map<std::string, std::set<std::string>> 的建议既不高效也不方便(因为已经编写了基于多图的代码)。

标签: c++ multimap


【解决方案1】:

std::map<std::string, std::set<std::string>> 似乎具有您正在寻找的属性(尽管复杂性不如unordered_mapunordered_set)。

【讨论】:

  • 他正在使用多重映射,因为他有多个键。
  • map 和 multimap 也允许 "a","a"。 DeadMG 的建议是可行的,但不适合我的情况(请参阅上面的评论......尤其是因为我使用 C++03 => 更担心复制构造函数。)
  • 我误解了这个问题。忽略我的评论。
【解决方案2】:

这是我想出的:

template<class K, class V>
typename multimap<K, V>::const_iterator find_pair(const multimap<K, V>& map, const pair<K, V>& pair)
{
    typedef multimap<K, V>::const_iterator it;
    std::pair<it,it> range = map.equal_range(pair.first);
    for (it p = range.first; p != range.second; ++p)
        if (p->second == pair.second)
            return p;
    return map.end();
}
template<class K, class V>
bool insert_if_not_present(multimap<K, V>& map, const pair<K, V>& pair)
{
    if (find_pair(map, pair) == map.end()) {
        map.insert(pair);
        return true;
    }
    return false;
}

(当有大量值附加到单个键时,这效率不高,但在我的情况下,每个键上的值很少。)

【讨论】:

  • 如果您使用返回的迭代器的唯一目的是进行比较,那么为什么不直接返回 bool 呢?
  • 因为谁知道呢,总有一天我可能想map.erase(find_pair(...))。诚然,contains_pair() 包装器也可能很方便。
【解决方案3】:

好像

      std::set<std::pair<std::string,std::string>>>

将拥有您正在寻找的属性。

但它既不是地图也不是多地图。您可以同时保留多图和一组键、值对,或者创建此组仅用于检查一致性。

我会使用这个集合并在它之上创建一个适配器到多映射接口。也许这不是最容易实施的解决方案,但具有最佳的性能效率。

请参阅“适配器设计模式”问题以获取参考。


[更新]

以我的working example 为起点。

例如如何遍历键的所有值 - 请参阅:

typedef  std::set<std::pair<std::string, std::string> > ssset;

ssset::iterator get_key(ssset& s, std::string key)
{
  ssset::iterator it = s.lower_bound(std::make_pair(key, ""));
  if (it != s.end() && it->first == key) return it;
  return s.end();   
}

for (ssset::iterator it = get_key(s, "abc"); it != s.end() && it->first == "abc"; ++it)
   std::cout << it->first << "->" << it->second << std::endl;

【讨论】:

  • 问题是现在我不能要求与键关联的值,因为搜索需要一对。
  • 可以搜索(key,"")的下限。如果用键找到它是第一个值。迭代直到另一个键开始。这可以包含在我提到的适配器中
【解决方案4】:

我对您的建议是将您的多地图包装在一个类中,然后在向地图中添加内容的方法中简单地进行验证。其余的函数将简单地传递给多图的方法。它编写了很多样板代码,但如果您需要进行其他类型的验证,这种方式会更容易。

【讨论】:

  • 你的建议是 O(N) 时间。
猜你喜欢
  • 2019-10-03
  • 2017-10-29
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
  • 1970-01-01
  • 2015-02-05
相关资源
最近更新 更多