繁体   English   中英

在C ++ STL中对3个向量进行交织/解交织

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM