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

C++ c++;:根据预定义的元素索引,选择std::vector的子集,c++,performance,vector,sample,subset,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"} 但我假设这将导致在每次迭代中通过selectionV,这比简单地添加所有元

我正在寻找一种修剪或复制现有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"}
但我假设这将导致在每次迭代中通过selectionV,这比简单地添加所有元素然后选择子集效率要低得多


非常感谢您的帮助。

您可以通过增加顺序对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++;
}
int index=0,nextInSelectionV=0;
for(Iterator.begin;nextInSelectionV
  • 这取决于
    Test
    的大小和
    SelectionV
    的大小(占
    Test
    的百分比),以及
    SelectionV
    中的元素是否重复。您可以通过计算
    而不是选择v
    来进行潜在的优化
  • 请注意,在您的示例中,由于
    SelectionV
    是一个索引,而不是一个值,因此查找速度已经快了O(1)(这已经是一个巨大的加号)
  • 如果
    Test
    SelectionV
    没有变化,并且如果它们很大,您还可以将
    SelectionV
    除以n个线程,让每个线程在
    Test
    中独立查找值,然后在以后合并各个输出(与map reduce不同)。缺点可能是CPU缓存命中丢失
  • 在重复呼叫时,您可能需要取旧的
    SelectionV
    和新的
    SelectionV
    之间的差异,并对该值进行操作。这种类型的缓存优化可以很好地用于迭代之间的少量更改
最重要的是,在花时间做这件事之前(更糟糕的是,使代码复杂化),确保您确实需要对此进行优化。


你的应用程序的其他部分(如I/O)很可能会慢很多倍。

也许以下内容对将来的人有用:

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;
}
模板
向量选择(常量标准::向量和向量,常量标准::大小索引)
{
断言(索引
您也可以使用标准库:

std::向量结果(SelectionV.size(),0)


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

selectionV是否需要是一个向量?填写测试/结果时它是静态的吗?SelectionV与Test相比有多大?(只有几个元素?几乎全部?)No selectionV不需要是向量。是测试/结果在填充时是静态的。SelectionV可能是测试的一个很大的百分比,但这是在运行时定义的,可以是任何百分比,尽管它肯定至少会有1000个索引。1)所需子集的相对大小会有所不同,并在运行时决定。2)最初将发生的是SelectionV将保持不变,试图从许多不同的“测试”中选择相同的子集。@oracle3001您实际分析过您的样本吗?设置selectionV和Test(尤其是在从磁盘或数据库读取数据时)实际上可能需要比选择算法更长的时间。我从中采样的对象是一系列网格对象(由OpenMesh.org库定义)。一旦加载到内存中,我将尝试从这些对象中重复采样顶点的子集。这是一个非常漂亮的解决方案!
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;
}