繁体   English   中英

c++ 保存插入顺序的容器

[英]c++ Container that preserve insertion order

我有一个 std::map 存储一个带有 std::any 向量的密钥。
目的是存储所有值并为每个键打印它们(使用不同的类型)。 没有对容器进行其他操作,只有“插入”和“清理”。

我想澄清一下容器经常被装满(和清空),所以我需要一个高效的容器。

这一切都适用于我的代码。 然而,问题是当我打印值时,它们是根据键排序的,但我必须按插入顺序打印(或存储)它们。

我的代码:

#include <iostream>
#include <map>
#include <vector>
#include <any>

std::map<int, std::vector<std::any>> testMap;

void insertMap(int value, std::vector<std::any> tempVector);
void printMap();


int main()
{   
    std::vector<std::any> tempVector;
    
    tempVector.clear();
    tempVector.push_back(1000);
    tempVector.push_back((std::string)"hello");
    tempVector.push_back(0.10f);
    insertMap(10, tempVector);
    
    
    tempVector.clear();
    tempVector.push_back(1500);
    tempVector.push_back((std::string)"hello2");
    tempVector.push_back(0.20f);
    insertMap(5, tempVector);
    
    tempVector.clear();
    tempVector.push_back(2000);
    tempVector.push_back((std::string)"hello3");
    tempVector.push_back(0.5f);
    insertMap(7, tempVector);

    // etc..
    
    printMap();
}

void insertMap(int value, std::vector<std::any> tempVector)
{
    testMap[value].insert(testMap[value].end(), tempVector.begin(), tempVector.end());
}


void printMap()
{
    for (const auto& [key, value] : testMap)
    {
       std::cout << "key=" << key << "\n";

        for(auto vec_iter : value)
        {
            if (vec_iter.type() == typeid(int))
                std::cout << "\t" << "int=" << std::any_cast<int>(vec_iter) << "\n";

            else if (vec_iter.type() == typeid(float))
                std::cout << "\t" << "float=" << std::any_cast<float>(vec_iter) << "\n";

            else if (vec_iter.type() == typeid(std::string))
                std::cout << "\t" << "string=" << std::any_cast<std::string>(vec_iter) << "\n";
        }
    }
}

Output:

key=5
key=7
key=10

预期 output:

key=10
key=5
key=7

我尝试使用unordered_map但它不按插入顺序打印它们。
那么我可以使用哪个容器? 在我的情况下,最好的表现是什么?
我认为我可以使用std::vector< std::map<int, std::vector<std::any>> > (存储std::mapvector )。 但它快吗? 有更好的解决方案吗?

没有标准库容器既可以通过密钥提供快速访问(这可能就是您开始使用std::map的原因)“保留插入顺序”。 如果你真的需要按键访问,那么迭代顺序就是你放弃控制的东西。

如果您需要恢复插入顺序,那么您将不得不保留它。 最简单的方法是将 map 迭代器的vector与您的map一起存储。 当您将一个项目插入map时,将它的新迭代器也推到vector的后面。

如果你在 position 中使用 Boost,可以求助于 Boost.MultiIndex:

现场 Coliru 演示

#include <iostream>
#include <vector>
#include <any>
#include <utility>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/key.hpp>

struct test_map_value_type
{
  test_map_value_type(int first, const std::vector<std::any>& second):
    first{first},second{second}{}
  
  int first;
  mutable std::vector<std::any> second;
};

boost::multi_index_container<
  test_map_value_type,
  boost::multi_index::indexed_by<
    boost::multi_index::ordered_unique<
      boost::multi_index::key<&test_map_value_type::first>
    >,
    boost::multi_index::sequenced<>
  >
> testMap;

void insertMap(int value, std::vector<std::any> tempVector);
void printMap();

int main()
{   
    std::vector<std::any> tempVector;
    
    tempVector.clear();
    tempVector.push_back(1000);
    tempVector.push_back((std::string)"hello");
    tempVector.push_back(0.10f);
    insertMap(10, tempVector);
    
    
    tempVector.clear();
    tempVector.push_back(1500);
    tempVector.push_back((std::string)"hello2");
    tempVector.push_back(0.20f);
    insertMap(5, tempVector);
    
    tempVector.clear();
    tempVector.push_back(2000);
    tempVector.push_back((std::string)"hello3");
    tempVector.push_back(0.5f);
    insertMap(7, tempVector);

    // etc..
    
    printMap();
}

void insertMap(int value, std::vector<std::any> tempVector)
{
    auto it=testMap.emplace(value,std::vector<std::any>{}).first;
    it->second.insert(it->second.end(), tempVector.begin(), tempVector.end());
}


void printMap()
{
    for (const auto& [key, value] : testMap.get<1>())
    {
       std::cout << "key=" << key << "\n";

        for(auto vec_iter : value)
        {
            if (vec_iter.type() == typeid(int))
                std::cout << "\t" << "int=" << std::any_cast<int>(vec_iter) << "\n";

            else if (vec_iter.type() == typeid(float))
                std::cout << "\t" << "float=" << std::any_cast<float>(vec_iter) << "\n";

            else if (vec_iter.type() == typeid(std::string))
                std::cout << "\t" << "string=" << std::any_cast<std::string>(vec_iter) << "\n";
        }
    }
}

Output

key=10
    int=1000
    string=hello
    float=0.1
key=5
    int=1500
    string=hello2
    float=0.2
key=7
    int=2000
    string=hello3
    float=0.5

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM