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";
}
}
}
输出:
key=5
key=7
key=10
预期输出:
key=10
key=5
key=7
我尝试使用 unordered_map
但它不会按插入顺序打印它们。
那么我可以使用哪个容器?在我的案例中,最好的表现是什么?
我认为我可以使用 std::vector< std::map<int, std::vector<std::any>> >
(存储 std::map
的 vector
)。但是速度快吗?有更好的解决方案吗?
没有标准的库容器同时提供按键快速访问(这大概是为什么你开始使用std::map
)and“保留插入顺序”。如果您真的需要按键访问,那么您可以放弃对迭代顺序的控制。
如果您需要恢复插入顺序,那么您将不得不保留它。最简单的方法是只在 map
旁边存储一个 vector
的地图迭代器。当您将一个项目插入 map
时,将它的新迭代器也推到 vector
的后面。
如果您可以使用 Boost,Boost.MultiIndex 可以使用:
#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
我有一个 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< std::map<int, std::vector<std::any>> >
(存储 std::map
的 vector
)。但是速度快吗?有更好的解决方案吗?
没有标准的库容器同时提供按键快速访问(这大概是为什么你开始使用std::map
)and“保留插入顺序”。如果您真的需要按键访问,那么您可以放弃对迭代顺序的控制。
如果您需要恢复插入顺序,那么您将不得不保留它。最简单的方法是只在 map
旁边存储一个 vector
的地图迭代器。当您将一个项目插入 map
时,将它的新迭代器也推到 vector
的后面。
如果您可以使用 Boost,Boost.MultiIndex 可以使用:
#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