【问题标题】:c++ Container that preserve insertion order保留插入顺序的c ++容器
【发布时间】:2021-02-16 14:54:34
【问题描述】:

我有一个 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";
        }
    }
}

输出:

key=5
key=7
key=10

预期输出:

key=10
key=5
key=7

我尝试使用unordered_map,但它没有按插入顺序打印它们。
那么我可以使用哪个容器?就我而言,最好的表现是什么?
我以为我可以使用std::vector&lt; std::map&lt;int, std::vector&lt;std::any&gt;&gt; &gt;(vector 那家商店std::map)。但它快吗?有没有更好的解决方案?

【问题讨论】:

  • "vec_iter.type() == typeid(int)" 您要查找的类型是std::variant,而不是std::any。事实上,几乎任何时候你打电话给std::any::type,你使用any是错误的。
  • Boost 有multi_index 容器。

标签: c++ containers c++17 stdmap insertion-order


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    如果你可以使用 Boost,可以使用 Boost.MultiIndex:

    Live Coliru Demo

    #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";
            }
        }
    }
    

    输出

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-24
      • 2010-10-14
      • 2012-12-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 2011-01-23
      • 1970-01-01
      相关资源
      最近更新 更多