【问题标题】:Interleaving/deinterleaving 3 vectors in C++ STL在 C++ STL 中交错/去交错 3 个向量
【发布时间】:2010-08-31 15:16:26
【问题描述】:

我正在尝试将三个信号波形组合成一个交错的波形。我需要知道在 C++ STL 中做到这一点的最佳方法。更好的解决方案会尽可能多地使用 C++ STL 风格,避免冗余代码等。是否有一些 STL“元组”类型的类可以为我做这件事?我始终需要连续存储以向后兼容其他代码(因此,向量)。最好的解决方案是正确且易于理解的。空间和速度不如正确性易于理解那么重要。

输出波形的顺序必须如下:第一个通道的第一个样本,第二个通道的第一个样本,第三个通道的第一个样本,然后继续每个通道的第二个样本,并重复所有样本。我知道所有三个输入波形都有相同数量的样本。

在 Matlab 中,我会这样做:

函数 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 dVector; typedef vector::iterator dVectorIT; dVector Interleave3(dVector a, dVector b, dVector c) { dVector 结果(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++=*比特; *rIT++=*cIT; } 返回结果; }

它有效,但有更好的方法吗?我希望可能有一些聪明的方法可以用 transform() 在一行中做到这一点。你能把b附加到a,然后将c附加到a,然后将临时的“a1a2a3...-b1b2b3...-c1c2c3...”向量转换为“a1b1c1a2b2c2a3b3c3...”吗?

额外问题:我还需要逆运算(将 3*N 个样本的输出波形拆分为 3 个向量,每个向量包含 N 个样本)。 Matlab 解决方案非常简单:

函数 [a, b, c]=Deinterleave3(outputWaveform) a=输出波形(1:3:结束); b=输出波形(2:3:结束); c=输出波形(3:3:结束);

C++ STL 看起来相当尴尬,我敢打赌还有比这更好的方法:

typedef vector dVector; typedef vector::iterator dVectorIT; void Deinterleave3(dVector outputWaveform, dVector &a, dVector &b, dVector &c) { 断言(!(outputWaveform.size()%3)); 明确(); b.清除(); 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 iterator”,但我不知道它是否会执行交错或去交错操作。

编辑:修复丢失的尖括号 ()。 HTML 过滤器吃掉了它们!此外,我对如何使用自定义迭代器解决此问题有了新的想法。

【问题讨论】:

  • 我不能定义一个增加 3 而不是 1 的自定义迭代器吗?我尝试但未能创建一个带有私有成员变量的通用迭代器,用于跳过(3)值的数量和值的总数。当它到达尽头时,它会环绕。例如,51 个元素将按以下顺序引用元素 [0]、[3]、[6]...[48]、[1]、[4]、...
  • zip 迭代器将“虚拟地”进行交错 - 即您可以像交错一样使用向量,因此您甚至不需要去交错。

标签: c++ stl signal-processing


【解决方案1】:

如果您愿意使用 Boost,您可以使用slices 来获得与您在 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。

【讨论】:

    【解决方案2】:

    我不确定交错,但您可以使用 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多