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

时间:2012-06-19 09:50:22

标签: c++ stl vector indices

我有两个载体

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 个答案:

答案 0 :(得分:4)

显然,这里非常优选简单的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;
});

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

答案 1 :(得分: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是兼容的输出迭代器,Mvalue_typebool的输入迭代器。不幸的是,缺乏概念导致了一个名副其实的模板“爆炸”。

答案 2 :(得分:2)

这样的事情?

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

答案 3 :(得分:2)

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

不幸的是,C ++标准算法不太适合组合。如果您不介意创建中间容器,则可以应用transform的二进制版本,然后应用copy_if(或C ++ 03中的remove_copy_if,谓词相反,或{ {1}}修改您的中间容器),然后是remove_if的一元版本。

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

transform

你现在可能已经确信(a)循环更好,(b)用其他结构替换循环是C ++中的观看者运动; - )

如果您需要进一步链接操作,那么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>(); } ); 也可以替换为迭代器适配器:std::transform

答案 4 :(得分: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.