使用STL对两个数组进行条件迭代
conditional iterator over two arrays with STL
我有两个数组。类型为int和bool。bool数组表示一个元素是否已经被删除。现在我想要一个函数,它返回一个迭代器,只迭代未删除的元素。重要的是,该函数不应该分配新的内存(比如在新向量中复制元素)。是否有一种方法可以用标准STL做到这一点?
std::array<int,5> element={ 1 , 2 , 4 , 8 , 10 };
std::array<bool,5> deleted={ true, true, false, false, true };
std::vector<int>::iterator getNotDeleted(){
...
}
的例子:
deleted= { true, true, false, false, true };
element= { 1 , 2 , 4 , 8 , 10 };
getNotDeleted should return a std::vector<int>::iterator that Iterates over
{4,8}
您可以为此编写一个迭代器,只需构造一个知道两个向量的迭代器,以及它在两个向量中的当前位置。然后,在推进迭代器时,跳过标记为已删除的任何元素。
template<class T>
struct maybe_deleted_iterator {
typedef int difference_type;
typedef T value_type;
typedef T& reference;
typedef T* pointer;
typedef std::forward_iterator_tag iterator_category;
maybe_deleted_iterator();
maybe_deleted_iterator(std::vector<T>& e, std::vector<bool>& d, bool is_beginning);
maybe_deleted_iterator& operator++();
reference operator*() const;
pointer operator->() const;
bool operator==(const maybe_deleted_iterator& rhs);
bool operator!=(const maybe_deleted_iterator& rhs);
private:
std::vector<T>* elements;
std::vector<bool>* deleted;
typename std::vector<T>::iterator e_iter;
std::vector<bool>::iterator d_iter;
};
然后,简单地迭代!
int main() {
std::vector<int> element = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
std::vector<bool> deleted = {1, 0, 0, 1, 1, 0, 1, 0, 1, 1};
maybe_deleted_iterator<int> it(element, deleted, true);
maybe_deleted_iterator<int> end(element, deleted, false);
for(; it!=end; ++it) {
std::cout << *it << ' ';
}
}
http://coliru.stacked-crooked.com/view?id=40e4d1a54f71643ee9f885f82d71fb46-50d9cfc8a1d350e7409e81e87c2653ba LeSnip3R建议将成员设置为开始/结束对,这样它就可以在任何两个容器上工作,但我认为这更容易理解学习。在实际代码中,我希望看到它在不提及特定容器(如vector
)的情况下完成。
你可以这样滚动你自己的:
#include <array>
#include <iostream>
#include <functional>
template <class T>
struct no_op : std::unary_function <T,bool>
{
bool operator() (const T& x) const
{
return x;
}
};
template <class ItSource,
class ItPredicate,
class PredMod = no_op<bool> >
class ConditionalIterator
{
ItSource _srcBegin;
ItSource _srcEnd;
ItPredicate _predBegin;
ItPredicate _predEnd;
void MoveNext()
{
while (_predBegin != _predEnd &&
_srcBegin != _srcEnd &&
PredMod()(!*_predBegin))
{
++_predBegin;
++_srcBegin;
}
}
public:
typedef ConditionalIterator & Reference;
typedef typename std::iterator_traits<ItSource>::value_type ValueType;
ConditionalIterator(ItSource srcBegin, ItSource srcEnd,
ItPredicate predBegin, ItPredicate predEnd)
: _srcBegin(srcBegin)
, _srcEnd(srcEnd)
, _predBegin(predBegin)
, _predEnd(predEnd)
{
MoveNext();
}
ConditionalIterator(ConditionalIterator const &other)
: _srcBegin(other._srcBegin)
, _srcEnd(other._srcEnd)
, _predBegin(other._predBegin)
, _predEnd(other._predEnd)
{
}
ConditionalIterator &operator=(ConditionalIterator const &other)
{
if (this != &other)
{
_srcBegin = other._srcBegin;
_srcEnd = other._srcEnd;
_predBegin = other._predBegin;
_predEnd = other._predEnd;
}
return (*this);
}
Reference operator++()
{
++_predBegin;
++_srcBegin;
MoveNext();
return (*this);
}
ConditionalIterator operator++(int)
{
ConditionalIterator cit = *this;
operator++();
return (cit);
}
operator bool() const
{
return (_srcBegin != _srcEnd &&
_predBegin != _predEnd);
}
ValueType operator*()
{
return (*_srcBegin);
}
};
template <class PredMod, class ItSource, class ItPred>
ConditionalIterator<ItSource, ItPred, PredMod> MakeConditionalIterator(ItSource srcBegin, ItSource srcEnd,
ItPred predBegin, ItPred predEnd)
{
return (ConditionalIterator<ItSource, ItPred, PredMod>(srcBegin, srcEnd, predBegin, predEnd));
}
这段代码远未完成,但它应该让您开始。然后像这样使用:
int main()
{
std::array<int,5> element={ 1 , 2 , 4 , 8 , 10 };
std::array<bool,5> deleted={ false, true, false, false, true };
auto cit_valid = MakeConditionalIterator<std::logical_not<bool> >(element.begin(), element.end(),
deleted.begin(), deleted.end());
auto cit_delete = MakeConditionalIterator<no_op<bool> >(element.begin(), element.end(),
deleted.begin(), deleted.end());
while (cit_delete)
{
std::cout << *cit_delete++ << std::endl;
}
while (cit_valid)
{
std::cout << *cit_valid++ << std::endl;
}
return (0);
}
因此,正如Mooing Duck在注释中所示,可以在数组的任意元素上定义迭代器。我的观点是正确的,但我仍然建议你考虑不那么麻烦的解决方案;你可以选择(这只是我想到的两种解决方案,还有很多):
- 排序数组保持有效的条目在前面,并且只从第一个元素迭代到第n个有效元素
- 使用一个容器,如
std::vector
或std::list
,实际上从你的数组中擦除元素,所以你可以用一个普通的迭代器对它们进行迭代(这的变体:复制你的原始数组的元素在std::vector
上,你可以执行删除,保持你的原始向量安全)
相关文章:
- MongoDB 使用数组中的 OR 条件构建查询
- C++ 将二维数组索引与条件语句中的函数值进行比较
- 将子字符串与字符串数组进行比较的 IF 条件会在C++中产生错误
- 如何在Char数组中搜索Char在IF条件语句中
- 整个数组作为C 的条件
- 有没有办法创建一个花哨的迭代器和相应的新数组,以便检查每个索引的索引值的条件?
- 使用位集获取数组项的条件总和,而无需使用循环
- 将非类非数组 prvalue 转换为符合 cv 条件的类型是否合法?
- 如何在没有 c++ 中的数组/算法的情况下对两个条件的字符串进行排序
- Bool Vector 2D数组在IF条件下使用
- 有条件的断点修饰符以查看数组是否已更改
- 有条件地确定字符串是否是数组的一部分
- 使用两个条件对结构数组进行排序 C++
- 无法弄清楚为什么我的程序在条件不为真时执行 if 语句(数组)
- 动态数组(如果满足条件供以后使用)
- 二维数组、IF条件检查
- 是否可以使用有条件选择的字符串文本初始化字符数组
- 条件运算符和数组/返回指向数组的指针
- 使用数组作为惠勒循环条件
- 有条件的大平面数组遍历和令人惊讶的短循环执行时间