迭代向量中属性具有特定值的元素范围

iterators to range of elements in a vector whose attributes have specific value

本文关键字:元素 范围 向量 属性 迭代      更新时间:2023-10-16

我有一个对象向量,我想返回属性具有特定值的元素范围。这是结构:

class A {
public:
  std::vector<B*> vec_;
  pair<vector<B*>::iterator, vector<B*>::iterator> getElements(unsigned int attr_val);
  unsigned int name() { return name_; }
private:
  unsigned int name_;
};
class B {
public:
  unsigned int attr() { return attr_; }
  A* source() { return source_; }
  B* dest() { return dest_; }
private:
  A* source_;
  B* dest_;
  unsigned int attr_;
};

向量vec_已按attr_dest_->name()排序(按该顺序)。现在我想返回所有元素,其attr_等于 attr_val .

什么是

合适的stl算法(或者甚至有一个向量成员函数?)来实现getElements(unsigned int attr_val)

你需要

一个值传递给equal_range,而显而易见的东西是指针。获得一个显而易见的方法就是创建一个具有正确值attr_B实例,并编写一个仅涉及attr()值的比较器。我假设您已经知道如何做到这一点,因为您设法对向量进行了排序;-)

如果向量中没有空指针,您可以改为这样做:

struct FindAttr {
    unsigned int attr;
    FindAttr(unsigned int attr) : attr(attr) {}
    bool operator()(B *left, B *right) {
        unsigned int leftval = left ? left->attr() : attr;
        unsigned int rightval = right ? right->attr() : attr;
        return leftval < rightval;
    }
};
...
return equal_range(vec_.begin(), vec_.end(), nullptr, FindAttr(value));

你可以把它做成一个lambda:

return equal_range(vec_.begin(), vec_.end(), nullptr, [=value](B *left, B *right) {
    unsigned int leftval = left ? left->attr() : attr;
    unsigned int rightval = right ? right->attr() : attr;
    return leftval < rightval;
});

您实际上可以完全删除指针,以给出我认为是"最干净"的解决方案:

struct FindAttr {
    bool operator()(B *left, unsigned int rightval) {
        return left->attr() < rightval;
    }
    bool operator()(unsigned int leftval, B *right) {
        return leftval < right->attr();
    }
};
...
return equal_range(vec_.begin(), vec_.end(), value, FindAttr());

AFAIK 与 lambda 没有直接等价物,因为 lambda 只能有一个调用签名。我想你可以写一个接受boost::variant的lambda(或任何从unsigned intB*隐式转换的类型,并记住它是哪一个)。

您正在寻找std::equal_range,它基本上可以满足您的需求。界面为:

pair<It, It> equal_range(It first,
                         It last,
                         const T& value,
                         Compare comp);

comp默认为 std::less ,而 又调用运算符 <

在您的情况下,实现可以是:

bool comparer(B* el, unsigned int value)
{
  return el->attr() < value;
}
pair<vector<B*>::iterator, vector<B*>::iterator> A::getElements(unsigned int attr_val)
{
  return equal_range(vec_.begin(), vec_end(), attr_val, comparer);
}