C++ std::map:由具有相等值的键组成的返回向量

C++ std::map:由具有相等值的键组成的返回向量,c++,algorithm,dictionary,duplicates,stdmap,C++,Algorithm,Dictionary,Duplicates,Stdmap,我有一个std::map对象。关键点是实体ID(整数)及其二维位置(向量)的值。目的是确定哪些实体处于 相同的位置 ID位置 1 {2,3} 5 {6,2} 12 {2,3} 54 {4,4} 92 {6,2} 我需要得到一个向量,向量由键组成,它们的值相等 上面示例输入数据的输出:{1,12},{5,92} 我知道我可以将2D位置复制到向量到向量,并循环第一级向量以找到相等的第二级向量的索引。然后,通过索引选择向量并再次循环找到相应的键,返回查找键 请建议一种更干净的方法。标准

我有一个
std::map
对象。关键点是实体ID(整数)及其二维位置(向量)的值。目的是确定哪些实体处于 相同的位置

ID位置
1   {2,3}
5   {6,2}
12  {2,3}
54  {4,4}
92  {6,2}
我需要得到一个向量,向量由键组成,它们的值相等

上面示例输入数据的输出:{1,12},{5,92}

我知道我可以将2D位置复制到向量到向量,并循环第一级向量以找到相等的第二级向量的索引。然后,通过索引选择向量并再次循环找到相应的键,返回查找键


请建议一种更干净的方法。

标准::映射的要点是提供有效的键到值的映射。您需要的是一个额外的键映射值-可以通过多种方式实现:

  • 有一个额外的
    std::map
    ,从
    Position
    std::vector

  • 使用某种空间分区数据结构(例如四叉树、空间哈希、网格),可以根据实体的位置高效地查找实体

  • 使用双向多贴图类似。这将允许您在值集合上进行双向映射,而不必使用多个数据结构

“我怎么选择?”


这取决于你的优先级。如果您想获得最大的性能,应该尝试所有的方法(可能使用某种模板化包装器)和配置文件。如果您想要优雅/整洁,
boost::bimap
似乎是最合适的解决方案。
std::map
的要点是提供有效的键到值的映射。您需要的是一个额外的键映射值-可以通过多种方式实现:

  • 有一个额外的
    std::map
    ,从
    Position
    std::vector

  • 使用某种空间分区数据结构(例如四叉树、空间哈希、网格),可以根据实体的位置高效地查找实体

  • 使用双向多贴图类似。这将允许您在值集合上进行双向映射,而不必使用多个数据结构

“我怎么选择?”


这取决于你的优先级。如果您想获得最大的性能,应该尝试所有的方法(可能使用某种模板化包装器)和配置文件。如果您想要优雅/整洁,
boost::bimap
似乎是最合适的解决方案。

您可以将地图中的数据放入
std::mutlimap
,其中
位置
作为键,
ID
作为值


作为旁注,我想知道对于二维点而言,std::pair是否比向量更好。

您可以将地图中的数据放入
std::mutlimap
,其中
位置
作为键,
ID
作为值


作为旁注,我想知道对于二维点,std::pair是否比向量更好。

您需要提供反向映射。有很多方法可以做到这一点,包括
multimap
,但是如果在创建映射后没有修改映射,一个简单的方法是迭代映射并构建反向映射。在反向映射中,映射值->键列表

下面的代码使用
std::unordered_map
std::pair
(原始映射中的值)映射到
std::vector
(原始映射中的键列表)。反向地图的构建简单明了:

std::unordered_map<Point, std::vector<int>, hash> r;
for (const auto& item : m) {
    r[item.second].push_back(item.first);
}

您需要提供一个反向映射。有很多方法可以做到这一点,包括
multimap
,但是如果在创建映射后没有修改映射,一个简单的方法是迭代映射并构建反向映射。在反向映射中,映射值->键列表

下面的代码使用
std::unordered_map
std::pair
(原始映射中的值)映射到
std::vector
(原始映射中的键列表)。反向地图的构建简单明了:

std::unordered_map<Point, std::vector<int>, hash> r;
for (const auto& item : m) {
    r[item.second].push_back(item.first);
}
似乎是最好的,但我还是会提供我的代码

给定

#包括
#包括
#包括
//向量2D的一些定义
结构向量2d{intx;inty;};
//向量2D上算子<的一些定义
布尔运算符b.x)返回false;
返回a.y
那么:

template <typename M>
auto calculate(M const & inputMap) -> std::vector<std::vector<typename M::key_type> > {
    std::map<typename M::mapped_type,
            std::vector<typename M::key_type> > resultMap;
    for (auto const & vp : inputMap)
        resultMap[vp.second].push_back(vp.first);
    std::vector<std::vector<typename M::key_type> > result;
    for (auto & vp: resultMap)
        if (vp.second.size() > 1)
            result.emplace_back(std::move(vp.second));
    return result;
}
模板
自动计算(M常量和输入映射)->std::vector{
映射结果映射;
用于(自动常量和vp:inputMap)
结果映射[vp.second]。推回(vp.first);
std::向量结果;
用于(自动和vp:resultMap)
如果(vp.second.size()>1)
结果:后置(标准::移动(副总裁秒));
返回结果;
}
以下是如何测试:

int main() {
    std::map<int, Vector2D> input{
        {1,  Vector2D{2,3}},
        {5,  Vector2D{6,2}},
        {13, Vector2D{2,3}},
        {54, Vector2D{4,4}},
        {92, Vector2D{6,2}}
    };

    auto const result = calculate(input);

    // Ugly print
    std::cout << '{';
    static auto const maybePrintComma =
        [](bool & print) {
            if (print) {
                std::cout << ", ";
            } else {
                print = true;
            }
        };
    bool comma = false;
    for (auto const & v: result) {
        maybePrintComma(comma);
        std::cout << '{';
        bool comma2 = false;
        for (auto const & v2: v) {
            maybePrintComma(comma2);
            std::cout << v2;
        }
        std::cout << '}';
    }
    std::cout << '}' << std::endl;
}
intmain(){
映射输入{
{1,向量2d{2,3},
{5,向量2d{6,2},
{13,向量2d{2,3},
{54,向量2d{4,4},
{92,向量2d{6,2}
};
自动常数结果=计算(输入);
//丑陋的印刷品
std::cout似乎是最好的,但无论如何我都会提供我的代码

给定

#包括
#包括
#包括
//向量2D的一些定义
结构向量2d{intx;inty;};
//向量2D上算子<的一些定义
布尔运算符b.x)返回false;
返回a.y
那么:

template <typename M>
auto calculate(M const & inputMap) -> std::vector<std::vector<typename M::key_type> > {
    std::map<typename M::mapped_type,
            std::vector<typename M::key_type> > resultMap;
    for (auto const & vp : inputMap)
        resultMap[vp.second].push_back(vp.first);
    std::vector<std::vector<typename M::key_type> > result;
    for (auto & vp: resultMap)
        if (vp.second.size() > 1)
            result.emplace_back(std::move(vp.second));
    return result;
}
模板
自动计算(M常量和输入映射)->std::vector{
映射结果映射;
用于(自动常量和vp:inputMap)
结果映射[vp.second]。推回(vp.first);
std::向量结果;
用于(自动和vp:resultMap)
如果(vp.second.size()>1)
结果:后置(标准::移动(副总裁秒));
返回结果;
}