我有两个载体
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
谢谢!
答案 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::begin
和std::end
需要C ++ 11。)
也就是说,库中的正确的实现可能会使用enable_if
(或static_assert
)来确保所使用的迭代器类型与其使用兼容,即I
是输入迭代器,O
是兼容的输出迭代器,M
是value_type
为bool
的输入迭代器。不幸的是,缺乏概念导致了一个名副其实的模板“爆炸”。
答案 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] << " ";
}