【问题标题】:Search in std::map for key that bounds the search value在 std::map 中搜索限制搜索值的键
【发布时间】:2018-08-19 08:20:24
【问题描述】:

假设如果我有 std::map<std::pair<int, int>, int>,其中键在 map 中是一对两个整数值。

是否有可能找到一个限制我正在寻找的值的键?

例如:如果地图包含:

key = {4, 9}

我可以根据x 大于4 和x 小于9 找到这个键吗?其中x 是某个整数值。

我希望这是有道理的。

【问题讨论】:

  • 必须遍历地图。
  • 检查lower_bound() - 1 ?
  • 如果您的键中有重叠范围怎么办?您可以有两个不同的范围,其中包含在地图中不相邻的值 x。
  • 我不清楚你在问什么。我建议发布一个minimal reproducible example,它会遍历地图并找出您要查找的内容。 SO 的某个人可能知道更好的方法。
  • @1201ProgramAlarm:没有重叠范围。

标签: c++ stdmap


【解决方案1】:

如果间隔不重叠,您可以这样做by using a slightly different map, utilising a transparent comparator:

std::map<std::pair<int, int>, int, std::less<>> themap;

好消息是现在比较是透明的,所以我们可以制作自己的类型来为我们做正确的事情:

struct target
{
    int value;
};
constexpr bool operator<(target a, std::pair<int, int> b) noexcept {
    return a.value <= b.first;
}
constexpr bool operator<(std::pair<int, int> a, target b) noexcept {
    return a.second <= b.value;
}

themap.find(target{value});

【讨论】:

    【解决方案2】:

    std::map 有一个 find() 函数,它只查找完全匹配,因为键被视为单个值(即使由多个元素组成作为您的映射)。

    但是,有两种候选解决方案可以解决您的问题,具体取决于您尝试实现的具体目标:

    1) 使用 equal_range()

    equal_range() 将为您提供由两个迭代器定义的范围。第一个指向一个不小于key的元素,第二个指向第一个大于key的元素。

    因此,如果您正在寻找与确切键相关的边界,那么它可能就是您要寻找的:

    auto r2 = m.equal_range ({1,2});
    if (r2.first!=m.end()) {
        std::cout<<"Found range1 -> "<< r2.first->second << std::endl;
    }
    if (r2.second!=m.end()) {
        std::cout<<"Found range2 -> "<< r2.second->second << std::endl;
    }
    //attention the r2.first==r2.second if exact value not found. 
    

    如果您只使用该对的第一个组件来查找边界,它不会为您提供部分搜索。但是您可以使用它来搜索对 (x, 0);这将比仅遍历整个地图更有效。

    auto r3 = m.equal_range ({x,0});
    for (auto r=r3.first; r!=m.end() && r->first.first==x; r++) {
        std::cout<<"In range -> "<< r->second << std::endl;
    }
    std::cout<<"That's all I found for <<x<<std::endl;
    

    这里是online demo。

    2) 使用地图地图

    如果您的问题与部分键有关,您只知道第一个元素,那么使用std::map&lt;int, std::map&lt;int, int&gt;&gt; 可能更容易。

    然后将简化对部分键的搜索:

    auto r3 = m.find (x);   // look for first component
    if (r3==m.end()) 
        std::cout<<"r3 not found"<<std::endl; 
    else for (auto r : r3->second) {  // iterate on second component
        std::cout<<"In range -> "<< r.second << std::endl;
    }
    

    然而,这种简单性是以搜索完整键的更高成本为代价的,因为您需要先查找第一个组件,然后再查找第二个组件。

    Demo code

    【讨论】:

      【解决方案3】:

      您可以使用 std::find_if 算法。查看this example on ideone

      #include <algorithm>
      #include <iostream>
      #include <map>
      #include <tuple>
      
      int main() {
        std::map<std::pair<int, int>, int> m { { {1,3}, 4 }, { {6, 10}, 5 }, { {123, 126}, 111 } };
        int x = 8;
      
        auto result = std::find_if(std::begin(m), std::end(m), [x](const auto& v) {
            return v.first.first < x && x < v.first.second;
        });
      
        if(result != std::end(m)) {
            std::cout << "FOUND x " << result->second;
        }
      
        return 0;
      }
      

      Map 可以被认为是对的vector,并且可以在算法库中的函数中使用。如果 Find_if 与谓词匹配(签名bool pred(const Type &amp;a);),则返回元素的迭代器。在您的情况下,类型是std::pair&lt;std::pair&lt;int,int&gt;, int&gt;。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-09
        • 2021-11-14
        • 2018-12-04
        • 2014-10-17
        • 1970-01-01
        • 1970-01-01
        • 2021-10-11
        相关资源
        最近更新 更多