【问题标题】:unordered_map find only items after the previously found itemunordered_map 仅查找先前找到的项目之后的项目
【发布时间】:2016-06-06 15:38:16
【问题描述】:

我有一个 unordered_map,它包含一个枚举和一个字符串作为第二个。第一个值可能以不同的顺序出现多次。这是一个例子:

enum SomeType
{
    TYPE1,
    TYPE2,
};

static std::unordered_map<SomeType, std::string> value_map =
{
    { TYPE2, "Value that shouldn't be found" },
    { TYPE1, "Value that gets found first" },
    { TYPE2, "Value that also never gets found" },
    { TYPE1, "Value that gets found second" },
    { TYPE2, "Value that gets found last" },
};

我想按如下方式遍历地图:例如,首先我想找到TYPE1 的配对,这将使我获得第一个TYPE1 值。之后再次搜索TYPE1 值不会让我获得第一个,而是可以在它之后找到的下一个。在此之后搜索 TYPE2 值只会得到最后一个值。
基本上我只想找到下一个匹配值,但在最后一个找到的值之前都没有。

我多次尝试实现这样的东西,但我不太确定如何实现这样的算法。
如何实现这样的算法?

尝试展示我想要的完整代码示例:https://godbolt.org/g/CgNZnj

【问题讨论】:

  • 仅供参考,地图的键必须是唯一的。不能有多个元素具有相同的键。
  • 注意组件名称,Unordered 映射。插入顺序与遍历顺序无关。
  • 你需要一个vector/deque/list/forward_list/array 对。所有关联容器,无论是有序的还是无序的,都需要唯一的键,或者将等效的键组合在一起。
  • “我有一个 unordered_map,它包含一个枚举和一个字符串作为第二个。第一个值可能会以不同的顺序出现多次。” 没有。

标签: c++ c++14 unordered-map


【解决方案1】:

你可能想要一个 std::unordered_multimap (multimap) 并使用 equal_range:

#include <algorithm>
#include <iostream>
#include <unordered_map>

enum SomeType
{
    TYPE1,
    TYPE2,
};

static std::unordered_multimap<unsigned, std::string> value_map =
{
    { TYPE2, "Value that shouldn't be found" },
    { TYPE1, "Value that gets found first" },
    { TYPE2, "Value that also never gets found" },
    { TYPE1, "Value that gets found second" },
    { TYPE2, "Value that gets found last" },
};

int main() {
    auto range = value_map.equal_range(TYPE1);
    for( auto i = range.first; i != range.second; ++i )
        std::cout << i->second << '\n';
}

但是:

  • 结果范围未排序(保持无序状态)。
  • 如果要保持初始化中使用的相等键的相对顺序,请将unordered_multimap 替换为multimap
  • 如果要完全保持初始化顺序,请使用键/值对的序列容器 (std::vector)。关联容器 set、map(及其无序和/或多变体)不保留顺序。

结论:

在关联容器上运行的算法中实现您的搜索要求是不可能的。

【讨论】:

  • 这里需要value_type吗?
  • @DieterLücking 在你的主目录中,如果你删除using value_type 行,而不是std::for_each 语句写for( auto i = range.first; i != range.second; ++i ) std::cout &lt;&lt; i-&gt;second &lt;&lt; '\n';,输出会和你现在的一样吗?
  • 可以使用 std::advance 将迭代器推进到所需位置(即最后使用的值),然后使用 for 在所需范围内的每个循环进行搜索(最后使用的迭代器 pos, end地图)以获得所需的值。这将实现我的目标。谢谢你的线索。
【解决方案2】:
#include <iostream>
#include <string>
#include <vector>
#include <utility>

enum SomeType
{
    TYPE1,
    TYPE2,
    TYPE3,
};

using value_map = std::vector<std::pair<SomeType, std::string>>;

class ValueMap
{
public:
    ValueMap(value_map& map) : map(map), index(0) {}

    value_map& map;

    std::string find_next(SomeType type)
    {
        while ((index != map.size()) && (map[index].first != type))
        {
            ++index;
        }

        if (index != map.size())
        {
            std::string result = map[index].second;
            ++index;
            return result;
        }
        else
        {
            return "-";
        }
    }

private:
    unsigned index;
};

static value_map some_value_map =
{
    { TYPE2, "Value that shouldn't be found" },
    { TYPE1, "Value that gets found first" },
    { TYPE2, "Value that also never gets found" },
    { TYPE1, "Value that gets found second" },
    { TYPE2, "Value that gets found last" },
};

static ValueMap value_mapper(some_value_map);

int main()
{
    std::cout << value_mapper.find_next(TYPE1) << std::endl;
    std::cout << value_mapper.find_next(TYPE1) << std::endl;
    std::cout << value_mapper.find_next(TYPE2) << std::endl;

    std::string some_string = value_mapper.find_next(TYPE1);

    if (some_string == "-")
    {
        std::cout << "Didn't find a match" << std::endl;
    }

    value_mapper.map.push_back({ TYPE3, "Value that gets after the last as new" });
    std::cout << value_mapper.find_next(TYPE3) << std::endl;

    return 0;
}

生产

Value that gets found first
Value that gets found second
Value that gets found last
Didn't find a match
Value that gets after the last as new

【讨论】:

  • 谢谢!这正是我想要的。
猜你喜欢
  • 1970-01-01
  • 2015-02-21
  • 2021-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多