[英]Interleaving/deinterleaving 3 vectors in C++ STL
我正在尝试将三个信号波形合并为一个交错的波形。 我需要知道在C ++ STL中执行此操作的最佳方法 。 更好的解决方案将使用尽可能多的C ++ STL样式,避免使用冗余代码等。是否有一些STL“元组”类型类可以为我做到这一点? 为了始终与其他代码(因此是向量)向后兼容,我始终需要连续存储。 最佳解决方案是正确且易于理解的。 空间和速度不像正确性和易于理解那样重要 。
输出波形必须这样排序:来自第一个通道的第一个采样,来自第二个通道的第一个采样,来自第三个通道的第一个采样,然后继续每个通道的第二个采样,并重复所有采样。 我知道所有三个输入波形具有相同数量的样本。
在Matlab中,我应该这样做:
function outputWaveform=Interleave3(a, b, c) outputWaveform=zeros([1 3*length(a)]); outputWaveform(1:3:end)=a(:); outputWaveform(2:3:end)=b(:); outputWaveform(3:3:end)=c(:);
这是我第一次尝试C ++ STL:
typedef vector<double> dVector; typedef vector<double>::iterator dVectorIT; dVector Interleave3(dVector a, dVector b, dVector c) { dVector result(0, 3*a.size()); dVectorIT aIT=a.begin(), bIT=b.begin(), cIT=c.begin(), rIT=result.begin(); for(; aIT != a.end(); ++aIT, ++bIT, ++cIT) { *rIT++=*aIT; *rIT++=*bIT; *rIT++=*cIT; } return result; }
它有效,但是有更好的方法吗? 我希望可能有一些聪明的方法可以通过transform()做到这一点。 您可以将b附加到a,然后将c附加到a,然后将临时的“ a1a2a3 ...- b1b2b3 ...- c1c2c3 ...”向量转换为“ a1b1c1a2b2c2a3b3c3 ...”吗?
额外的问题:我还需要逆运算(将3 * N个样本的输出波形分成每个N个样本的3个向量)。 Matlab解决方案非常简单:
function [a, b, c]=Deinterleave3(outputWaveform) a=outputWaveform(1:3:end); b=outputWaveform(2:3:end); c=outputWaveform(3:3:end);
C ++ STL似乎很笨拙,我敢打赌,有比这更好的方法了:
typedef vector<double> dVector; typedef vector<double>::iterator dVectorIT; void Deinterleave3(dVector outputWaveform, dVector &a, dVector &b, dVector &c) { ASSERT( !(outputWaveform.size()%3) ); a.clear(); b.clear(); c.clear(); dVectorIT oIT=outputWaveform.begin(); for(; oIT != outputWaveform.end(); ) { a.push_back( *oIT++ ); b.push_back( *oIT++ ); c.push_back( *oIT++ ); } }
是否存在将进行逆运算的transform()和back_inserter()的巧妙组合? 同样,使用临时向量也是可以接受的。
Boost有一个“ zip迭代器 ”,但是我不知道它会执行交织还是去交织操作。
编辑:修复了缺少的尖括号(<>)。 HTML过滤器把它们吃掉了! 另外,我对如何使用自定义迭代器解决此问题有了新的想法。
如果您愿意使用Boost,则可以使用slice来使语法非常接近Matlab中的代码。 这是Interleave3函数的C ++版本:
template<typename V>
V Interleave3(V const& a, V const& b, V const& c)
{
using namespace boost::numeric::ublas;
V v(a.size() + b.size() + c.size());
vector_slice<V>(v, slice(0, 3, a.size())) = a;
vector_slice<V>(v, slice(1, 3, b.size())) = b;
vector_slice<V>(v, slice(2, 3, c.size())) = c;
return v;
}
要注意的是,必须使用boost :: numeric :: ublas :: vector而不是std :: vector。
我不确定交错,但是您可以使用for_each
进行交错。 您仍然需要添加其他错误检查(源大小正确等):
#include <iostream>
#include <vector>
typedef std::vector<double> dVector;
typedef dVector::iterator dVectorIT;
class DeInterleave
{
public:
DeInterleave(std::vector<dVector>& output) : output_(output), currentIndex_(0) { }
void operator()(const dVector::value_type& item)
{
output_[currentIndex_].push_back(item);
currentIndex_ = (currentIndex_ + 1) % output_.size();
}
private:
std::vector<dVector>& output_;
int currentIndex_;
};
int main()
{
dVector source;
source.push_back(5.0);
source.push_back(6.0);
source.push_back(8.0);
source.push_back(2.0);
source.push_back(2.0);
source.push_back(1.0);
std::vector<dVector> dest(3);
std::for_each(source.begin(), source.end(), DeInterleave(dest));
std::cout << dest[0].size() << " " << dest[0][0] << ":" << dest[0][1] << std::endl;
std::cout << dest[1].size() << " " << dest[1][0] << ":" << dest[1][1] << std::endl;
std::cout << dest[2].size() << " " << dest[2][0] << ":" << dest[2][1] << std::endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.