c ++:根据预定义的元素索引选择std :: vector的子集

时间:2012-03-10 22:20:05

标签: c++ performance vector sample subset

我正在寻找一种修剪或复制现有std :: vector子集的有效方法。符合子集/保留条件的元素的标准是它们的索引包含在单独的预定义std :: vector中。

e.g std::vector<String> Test = { "A", "B", "C", "D", "E"}

std::vector<int> SelectionV = {1,2,5}

Result = {"A", "B", "E"}

我将在一个非常大的矢量上执行此操作,并且可能会定期执行此操作,因此我正在寻找尽可能有效的方法。

我也在考虑另一种选择,但又不确定一种有效的方法是......

当对象Test被填充时(在我的情况下它是第三方定义的对象),它是使用迭代器进行单次传递的结果(不能直接访问元素)。我想知道是否可以只添加出现在SelectionV中定义的计数中的Test向量元素

例如

int count = 0

for (Iterator.begin, Iterator.end(), Iterator++) {
    if (count is a number contained in selectionV)
        add to Test
}

但我认为这会导致每次迭代都通过selectionV,这比简单地添加所有元素并稍后选择子集要低得多。

任何帮助都非常感激。

4 个答案:

答案 0 :(得分:4)

您也可以使用标准库:

std::vector<std::string> Result(SelectionV.size(), 0);

std::transform(SelectionV.begin(), SelectionV.end(), Result.begin(), [Test](size_t pos) {return Test[pos];});

答案 1 :(得分:1)

您可以通过增加顺序对SelectionV矢量进行排序,然后您可以重写您的for循环,例如:

int index = 0, nextInSelectionV = 0;
for (Iterator.begin; nextInSelectionV < SelectionV.lengh() && Iterator.end(); Iterator++) {
    if (index == SelectionV[nextInSelectionV]) {
        add to Test
        nextInSelectionV++;
    }
    index++;
}

答案 2 :(得分:1)

  • 这取决于Test的大小和SelectionV的大小(Test的百分比),以及SelectionV中的元素是否重复。您可以通过计算Not SelectionV来优化。
  • 请注意,在您的示例中,由于SelectionV是一个索引,而不是一个值,因此查找已快速为O(1)(这已经是一个巨大的优势)。
  • 如果TestSelectionV没有变化,如果它们很大,您还可以将SelectionV除以 n个帖子,并让每个帖子独立查找Test中的值,然后稍后合并各个输出(与map-reduce不同)。缺点可能是CPU缓存命中率下降。
  • 在重复通话时,您可能希望区分旧SelectionV和新SelectionV之间的差异并对此值进行操作。这种类型的缓存优化适用于迭代之间的少量更改。

最重要的是,确保在花费时间之前确实需要对其进行优化(更糟糕的是,使代码复杂化)。

您应用的其他部分(例如I / O)很可能会慢一些。

答案 3 :(得分:0)

以下可能对以后的人有用:

template<typename T>
T vector_select(const std::vector<T>& vector, const std::size_t index)
{
  assert(index < vector.size());  
  return vector[index];
}

template<typename T>
class VectorSelector
{
public:
  VectorSelector(const std::vector<T>& v) : _v(&v) { }
  T operator()(const std::size_t index){ return vector_select(*_v, index); }
private:
  const std::vector<T>* _v;

};

template<typename T>
std::vector<T> vector_select(const std::vector<T>& vector,
                             const std::vector<std::size_t>& index)
{
  assert(*std::max_element(index.begin(), index.end()) < vector.size());
  std::vector<T> out(index.size());
  std::transform(index.begin(), index.end(), out.begin(),
                 VectorSelector<T>(vector));
  return out;
}