将 3 std::vector 组合成临时单个 std::vector 的最简单方法?
Easiest way to combine 3 std::vector into a temporary single std::vector?
我看过这个讨论(Concatenating two std::vectors),但它涉及组合(如移动)两个std::vector
数组。
我有 three std::vectors
我正在使用 C++17:
m_mapHist[m_eHistAssign][strName]
m_mapScheduleHist[m_eHistAssign][strName]
m_mapScheduleFutureHist[m_eHistAssign][strName]
每个向量的类型都是 std::vector<COleDateTime>
。我不想改变这些向量。相反,我想将它们组合(copy 我猜)到一个临时的单个向量中,这样我就可以将一个向量传递给另一个 class 进行处理。
目前我正在通过迭代手动执行此操作:
std::vector<COleDateTime> vecAssignmentDate;
// Past items from the history database
if (m_mapHist[m_eHistAssign].find(strName) != m_mapHist[m_eHistAssign].end())
{
for (const auto& historyItemDate : m_mapHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
// Past items on the active schedule
if (m_mapScheduleHist[m_eHistAssign].find(strName) != m_mapScheduleHist[m_eHistAssign].end())
{
for (const auto& historyItemDate : m_mapScheduleHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
// Future items (both on the active schedule and in the history database)
if (m_mapScheduleFutureHist[m_eHistAssign].find(strName) != m_mapScheduleFutureHist[m_eHistAssign].end())
{
for(const auto &historyItemDate : m_mapScheduleFutureHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
有没有更简单的方法来创建这个临时向量?
您可以使用 boost::join
。示例:
std::vector<COleDateTime> v1;
std::vector<COleDateTime> v2;
std::vector<COleDateTime> v3;
std::vector<COleDateTime> result;
result = boost::join(boost::join(v1, v2), v3);
自 c++17 起,标准也有一个 std::merge
util 函数:
std::vector<COleDateTime> v1;
std::vector<COleDateTime> v2;
std::vector<COleDateTime> v3;
std::vector<COleDateTime> result;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
std::merge(v3.begin(), v3.end(), result.begin(), result.end(), std::back_inserter(result));
std::merge
和 std::copy
之间的区别
来自 cplusplus.com/reference/algorithm/merge/ std::merge
:
Combines the elements in the sorted ranges [first1,last1) and [first2,last2), into a new range beginning at result with all its elements sorted.
来自 cplusplus.com/reference/algorithm/copy/ std::copy
:
Copies the elements in the range [first,last) into the range beginning at result..
所以这取决于你想要达到什么。
使用标准库,您可以做到这一点。顺便说一句,我还没有测试代码。它可能包含错误。
#include <algorithm>
template<typename T, typename U, typename ...Args>
std::vector<COleDateTime> combine(T key1, U key2, Args ...arg) {
std::vector<COleDateTime> ret;
for (const auto& v : {arg...}) {
if (v[key1].find(key2) != v[key1].cend()) {
std::copy(v[key1][key2].begin(), v[key1][key2].end(), std::back_inserter(ret));
}
}
return ret;
}
简单的复制赋值有什么问题?
const std::vector<COleDateTime>& v1;
const std::vector<COleDateTime>& v2;
const std::vector<COleDateTime>& v3;
std::vector<COleDateTime> result;
result.reserve(v1.size() + v2.size() + v3.size());
for(const std::vector<COleDateTime>* vec: {&v1, &v2, &v3})
result.insert(result.end(), vec->begin(), vec->end());
由于您的输入向量可能不存在,这里有一个版本可以解决这个问题:
using vector_type = std::vector<COleDateTime>;
using map_type = std::map<std::string, vector_type>;
auto find_or_null = [](const map_type& map, const std::string& key) noexcept
-> const vector_type* {
map_type::const_iterator found = map.find(key);
return found == map.end() ? nullptr : &found->second;
};
const auto vecs = { find_or_null(n_mapHist, strName),
find_or_null(m_mapScheduleHist, strName),
find_or_null(m_mapScheduleFutureHist, strName)
};
std::size_t size = 0;
for(const vector_type* vec: vecs)
if(vec)
size += vec->size();
vector_type result;
result.reserve(size);
for(const vector_type* vec: vecs)
if(vec)
result.insert(result.end(), vec->begin(), vec->end());
我看过这个讨论(Concatenating two std::vectors),但它涉及组合(如移动)两个std::vector
数组。
我有 three std::vectors
我正在使用 C++17:
m_mapHist[m_eHistAssign][strName]
m_mapScheduleHist[m_eHistAssign][strName]
m_mapScheduleFutureHist[m_eHistAssign][strName]
每个向量的类型都是 std::vector<COleDateTime>
。我不想改变这些向量。相反,我想将它们组合(copy 我猜)到一个临时的单个向量中,这样我就可以将一个向量传递给另一个 class 进行处理。
目前我正在通过迭代手动执行此操作:
std::vector<COleDateTime> vecAssignmentDate;
// Past items from the history database
if (m_mapHist[m_eHistAssign].find(strName) != m_mapHist[m_eHistAssign].end())
{
for (const auto& historyItemDate : m_mapHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
// Past items on the active schedule
if (m_mapScheduleHist[m_eHistAssign].find(strName) != m_mapScheduleHist[m_eHistAssign].end())
{
for (const auto& historyItemDate : m_mapScheduleHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
// Future items (both on the active schedule and in the history database)
if (m_mapScheduleFutureHist[m_eHistAssign].find(strName) != m_mapScheduleFutureHist[m_eHistAssign].end())
{
for(const auto &historyItemDate : m_mapScheduleFutureHist[m_eHistAssign][strName])
{
vecAssignmentDate.push_back(historyItemDate);
}
}
有没有更简单的方法来创建这个临时向量?
您可以使用 boost::join
。示例:
std::vector<COleDateTime> v1;
std::vector<COleDateTime> v2;
std::vector<COleDateTime> v3;
std::vector<COleDateTime> result;
result = boost::join(boost::join(v1, v2), v3);
自 c++17 起,标准也有一个 std::merge
util 函数:
std::vector<COleDateTime> v1;
std::vector<COleDateTime> v2;
std::vector<COleDateTime> v3;
std::vector<COleDateTime> result;
std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(result));
std::merge(v3.begin(), v3.end(), result.begin(), result.end(), std::back_inserter(result));
std::merge
和 std::copy
来自 cplusplus.com/reference/algorithm/merge/ std::merge
:
Combines the elements in the sorted ranges [first1,last1) and [first2,last2), into a new range beginning at result with all its elements sorted.
来自 cplusplus.com/reference/algorithm/copy/ std::copy
:
Copies the elements in the range [first,last) into the range beginning at result..
所以这取决于你想要达到什么。
使用标准库,您可以做到这一点。顺便说一句,我还没有测试代码。它可能包含错误。
#include <algorithm>
template<typename T, typename U, typename ...Args>
std::vector<COleDateTime> combine(T key1, U key2, Args ...arg) {
std::vector<COleDateTime> ret;
for (const auto& v : {arg...}) {
if (v[key1].find(key2) != v[key1].cend()) {
std::copy(v[key1][key2].begin(), v[key1][key2].end(), std::back_inserter(ret));
}
}
return ret;
}
简单的复制赋值有什么问题?
const std::vector<COleDateTime>& v1;
const std::vector<COleDateTime>& v2;
const std::vector<COleDateTime>& v3;
std::vector<COleDateTime> result;
result.reserve(v1.size() + v2.size() + v3.size());
for(const std::vector<COleDateTime>* vec: {&v1, &v2, &v3})
result.insert(result.end(), vec->begin(), vec->end());
由于您的输入向量可能不存在,这里有一个版本可以解决这个问题:
using vector_type = std::vector<COleDateTime>;
using map_type = std::map<std::string, vector_type>;
auto find_or_null = [](const map_type& map, const std::string& key) noexcept
-> const vector_type* {
map_type::const_iterator found = map.find(key);
return found == map.end() ? nullptr : &found->second;
};
const auto vecs = { find_or_null(n_mapHist, strName),
find_or_null(m_mapScheduleHist, strName),
find_or_null(m_mapScheduleFutureHist, strName)
};
std::size_t size = 0;
for(const vector_type* vec: vecs)
if(vec)
size += vec->size();
vector_type result;
result.reserve(size);
for(const vector_type* vec: vecs)
if(vec)
result.insert(result.end(), vec->begin(), vec->end());