如何根据另一个向量中给出的索引拆分向量?
How to split vector according to indices given in another vector?
我有一个源std::vector<double>
,我想根据std::vector<int>
中包含的索引进行拆分。拆分是包含的,下一个切片的开始应从上一个中断的地方开始,从源矢量的开始开始。
例如:
{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 } -> source
{2, 4, 7 } -> split indices
应用函数后,它应该产生:
{1.1, 2.2, 3.3}
{4.4, 5.5}
{6.6, 7.7, 8.8}
我有这个不会给我第三个向量,依此类推:
vector<double> nets{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
vector<int> ends{2, 4, 7 };
vector<vector<double>> periodnumbers;
vector<double> numbers;
for (int i = 0; i < nets.size(); i++)
{
double temp;
temp = nets[i];
numbers.push_back(temp);
for (int j = 0; j < ends.size(); j++)
{
if (i == ends[j])
{
periodnumbers.push_back(numbers);
numbers.clear();
}
}
}
算法错误
即使它有效,它也做了太多不必要的操作。从遍历所有元素开始,以push_back
ing结束,而不是保留/调整大小。
更好的算法
假设ends
已排序。然后人们可以拿两个"滑块",并继续移动它们。左侧滑块从源矢量的开头开始,右侧滑块从第一端开始。随着算法的进展,它会复制滑块内的当前范围,将左滑块移动到右滑块,右滑块成为下一端。
#include <vector>
#include <algorithm>
std::vector<std::vector<double>> split_ends(const std::vector<double>& source, const std::vector<int>& ends) {
std::vector<std::vector<double>> result;
result.reserve(ends.size());
auto anchor_front = source.begin();
for (auto one_end: ends) {
auto anchor_end = std::next(source.begin(), one_end + 1);
result.emplace_back(anchor_front, anchor_end);
anchor_front = anchor_end;
}
return result;
}
#include <iostream>
void print(const std::vector<double>& v)
{
for (auto x: v) {
std::cout << x << ' ';
}
}
int main() {
std::vector<double> nets{1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9};
std::vector<int> ends{2, 4, 7};
auto splitted = split_ends(nets, ends);
for (const auto& v: splitted) {
print(v);
std::cout << 'n';
}
}
魔杖盒上的演示。
输出:
1.1 2.2 3.3
4.4 5.5
6.6 7.7 8.8
上面的算法假设ends
已排序并且不包含超出范围的索引。如果不需要副本,则可能只需保存端点迭代器,并直接对源执行更改。
if(i == ends[i])
中存在错误
一种选择是使用另一个变量。
vector<double> nets{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
vector<int> ends{2, 4, 7};
vector<vector<double>> periodnumbers;
vector<double> numbers;
int j=0;
for (int i = 0; i < nets.size(); i++)
{
double temp;
temp = nets[i];
numbers.push_back(temp);
//cout<<numbers[i]<<endl;
if (i == ends[j])
{
//cout<<i<<" "<<nets[i]<<endl;
periodnumbers.push_back(numbers);
numbers.clear();
j++;
//break;
}
//cout<<numbers[i]<<endl;
}
cout<<"Size"<<periodnumbers.size()<<endl;
for(int i=0;i<periodnumbers.size();i++){
for(int j=0;j<periodnumbers[i].size();j++){
cout<<periodnumbers[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
有很多细节我不确定你是否考虑过。我的答案是可以调整的。
特别是,我希望WEIRD_OFFSET
为 0。
#include <cassert>
#include <iostream>
#include <vector>
using std::cout;
using std::vector;
const bool ONLY = true;
const bool BEFORE_FIRST = true;
const bool AFTER_LAST = true;
const bool ALLOW_EMPTY = true;
const size_t WEIRD_OFFSET = 1;
template<class T>
vector<vector<T>> frob(const vector<T>& nets, const vector<int>& ends)
{
vector<vector<T>> rv;
if (ends.empty())
{
if (ONLY)
{
if (ALLOW_EMPTY || !nets.empty())
rv.push_back(nets);
}
}
else
{
if (BEFORE_FIRST)
{
auto bi = 0;
auto ei = ends[0] + WEIRD_OFFSET;
assert (0 <= bi && bi <= ei && ei <= nets.size());
auto b = nets.begin() + bi;
auto e = nets.begin() + ei;
if (ALLOW_EMPTY || b != e)
rv.push_back(vector<T>(b, e));
}
for (size_t i = 0; i < ends.size() - 1; ++i)
{
auto bi = ends[i] + WEIRD_OFFSET;
auto ei = ends[i+1] + WEIRD_OFFSET;
assert (0 <= bi && bi <= ei && ei <= nets.size());
auto b = nets.begin() + bi;
auto e = nets.begin() + ei;
if (ALLOW_EMPTY || b != e)
rv.push_back(vector<T>(b, e));
}
if (AFTER_LAST)
{
auto bi = ends.back() + WEIRD_OFFSET;
auto ei = nets.size();
assert (0 <= bi && bi <= ei && ei <= nets.size());
auto b = nets.begin() + bi;
auto e = nets.begin() + ei;
if (ALLOW_EMPTY || b != e)
rv.push_back(vector<T>(b, e));
}
}
return rv;
}
int main()
{
vector<double> nets{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
vector<int> ends{2, 4, 7};
vector<vector<double>> periodnumbers = frob(nets, ends);
for (const auto& v : periodnumbers)
{
for (const auto& i : v)
{
cout << i << ' ';
}
cout << 'n';
}
cout << std::flush;
}
这会产生:
1.1 2.2 3.3
4.4 5.5
6.6 7.7 8.8
9.9
如果我们可以假设ends
是按升序排序的,并且ends
中的值永远不会大于nets
允许的大小,那么有一个相当简单的函数可以给你想要的结果:
template<typename T>
std::vector<std::vector<T>> split(const std::vector<T>& nets, const std::vector<int>& ends)
{
std::vector<std::vector<T>> result;
int previous_offset = 0;
for (int i : ends)
{
const std::vector<T> piece(nets.begin() + previous_offset, nets.begin() + i + 1);
previous_offset = i;
result.push_back(piece);
}
return result;
}
包含示例数据的整个程序可能如下所示:
#include <iostream>
#include <vector>
// function from above
template<typename T>
std::vector<std::vector<T>> split(const std::vector<T>& nets, const std::vector<int>& ends)
{
std::vector<std::vector<T>> result;
int previous_offset = 0;
for (int i : ends)
{
const std::vector<T> piece(nets.begin() + previous_offset, nets.begin() + i + 1);
previous_offset = i;
result.push_back(piece);
}
return result;
}
int main()
{
// input data
std::vector<double> nets{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
std::vector<int> ends{2, 4, 7 };
// variable that will hold the result
std::vector<std::vector<double>> periodnumbers;
// This is where the work happens.
periodnumbers = split(nets, ends);
// Write result to standard output.
std::cout << "There are " << static_cast<int>(periodnumbers.size()) << " pieces:" << std::endl;
for (auto vec : periodnumbers)
{
std::cout << "Next piece is: ";
for (auto elem: vec)
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
return 0;
}
输出将是:
There are 3 pieces:
Next piece is: 1.1 2.2 3.3
Next piece is: 3.3 4.4 5.5
Next piece is: 5.5 6.6 7.7 8.8
我建议以下更简单,更容易理解的代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<double> nets{ 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 };
vector<int> ends{2, 4, 7 };
ends.push_back(nets.size()-1);
vector<vector<double>> periodnumbers;
vector<double> numbers;
int j=0;
int coming_split_index=ends[j];
for (int i = 0; i < nets.size(); i++){
if(i<=coming_split_index){
numbers.push_back(nets[i]);
}else{
j++;
coming_split_index=ends[j];
periodnumbers.push_back(numbers);
numbers.clear();
i--;
/*when the index i reaches the coming index the corresponding
*value won't be added to any subvector because It will skip the
*pervious instruction for this reason I decrement the counter i so
*that it repeats it and the next time the one in the previous will
*be executed
*/
}
}
这将显示您的结果
1.1 2.2 3.3
4.4 5.5
6.6 7.7 8.8
相关文章:
- 在C++中调整向量中的索引
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 将转换字符键入 int 以用作向量C++的索引
- 在对向量中查找元素的索引
- 如何检查类实例向量的索引是否为空
- 如何根据排序索引的向量对 std::index 集进行排序?
- 向量索引变量声明(size_t 或 std::vector<DATATYPE>::size_type)
- 访问向量索引C++
- 包含全局最小值的向量索引
- C 向量由另一个向量索引
- 向量索引在C 中不会包裹吗?什么是解决方法
- 使用Armadillo库中的指数向量索引矩阵
- 将多个整数添加到一个向量索引? 'Cout'不起作用
- array:将一维数组的索引转换为多维数组的向量索引
- 将一维"flattened"索引转换为 N 维数组的 N 维向量索引
- 向量索引访问与迭代器访问的效率
- 特征矩阵支持由向量索引吗?
- 如何重写由向量索引指向的项?
- 在另一个向量中引用向量索引时出错:'std::out_of_range at memory location'
- c++帮助传递向量索引到函数