首页 文章

如何获取向量的那些元素,其中另一个向量在相应的索引处具有'1' s

提问于
浏览
3

我有两个向量

std::vector<int>   markedToBeRead(7);   // contains: 1,1,0,0,1,0,1
std::vector<float> myVec(7);            // contains: 1,2,3,4,5,6,7

从myVec中获取这些元素的最佳方法是什么,其中 markedToBeRead 的相应索引具有值 1 .
这可能不使用for循环,但使用stl方法?

std::vector<float> myResult;            // contains: 1,2,5,7

谢谢!

5 回答

  • 2

    显然,这里非常优选简单的for循环而不是任何STL算法 .

    但是作为一个概念的证明,人们可以在这里采用stl :: equals和一个来自C 11的lambda:

    std::equal(myVec.begin(), myVec.end(), markedToBeRead.begin(), [&](float item, int mark)->bool {
        if (mark)
            myResult.push_back(item);
        return true;
    });
    

    这有效,但看起来很难看 .

  • 3

    以下是我为此编写算法的方法:

    template <typename I, typename O, typename M>
    void mask_copy(I begin, I end, O obegin, M mbegin) {
        for (; begin != end; ++begin, ++mbegin)
            if (*mbegin)
                *obegin++ = *begin;
    }
    

    这样称呼:

    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 , 9 };
    bool m[] = { true, false, false, false, true, false, false, true, false };
    
    std::vector<int> out;
    mask_copy(begin(a), end(a), back_inserter(out), begin(m));
    

    std::beginstd::end 需要C 11 . )

    也就是说,库中的正确实现可能会使用 enable_if (或 static_assert )来确保所使用的迭代器类型与其使用兼容,即 I 是输入迭代器, O 是兼容的输出迭代器, M 是输入迭代器, value_typebool . 不幸的是,缺乏概念会导致真正的模板爆炸 .

  • 4

    在功能方面,这很简单:它是两个输入范围的拉链,然后标记上的过滤器为1,接着是map以仅提取值 .

    不幸的是,C标准算法并不是创造中间容器,你可以应用 transform 的二进制版本,然后是 copy_if (或C03中的 remove_copy_if ,谓词反转,或 remove_if 来修改你的中间容器),然后是 transform 的一元版本 .

    或者,Boost以迭代器适配器的形式提供前两个操作 . 像这样(未经测试):

    struct marked {
        bool operator()(boost::tuple<int, float> t) {
            return t.get<0>() == 1;
        }
    };
    
    auto first = boost::make_zip_iterator(boost::make_tuple(markedToBeRead.begin(), myVec.begin());
    auto last = boost::make_zip_iterator(boost::make_tuple(markedToBeRead.end(), myVec.end());
    
    std::transform(
        boost::make_filter_iterator<marked>(first, last),
        boost::make_filter_iterator<marked>(last, last),
        std::back_inserter(myResults);
        [](boost:tuple<int, float> t) { return t.get<1>(); }
    );
    

    你现在可能已经确信(a)循环更好,而且(b)用C替换循环是一种观察性运动;-)

    如果需要链接进一步的操作,那么 std::transform 也可以用迭代器适配器替换: transform_iterator .

  • 2

    这样的事情?

    for (unsigned int i = 0; i < myVec.length(); i++)
        if (markedToBeRead[i] == 1)
            myResult.push_back(myVec[i]);
    
  • 0

    这对我有用:

    #include <algorithm>
    #include <iostream>
    #include <vector>
    
    int main()  {
            std::vector<int>   markedToBeRead = {  1,1,0,0,1,0,1 };
            std::vector<float> myVec = { 1, 2, 3, 4, 5, 6, 7};
    
            // copy
            std::vector<float> result;
            std::copy_if(myVec.begin(), myVec.end(),
                    std::back_inserter(result), [&](const float & f) {
                            return markedToBeRead[&f - &myVec[0]] == 1;
                    });
    
            // Check result
            for (std::vector<float>::size_type i = 0; i < result.size(); ++i)
                    std::cout << result[i] << " ";
    }
    

    Tested on Ideone.

相关问题