获取 std::set 子集的有效方法

Efficient way to get subset of std::set

我调用了一个库函数,它接受指向 std::set 的指针并处理它的元素。

但是,它只处理一定数量的元素(比如 100 个),如果该集合有更多元素,它只会抛出异常。但是,我收到了一套更大的尺寸。所以我需要有效的方法来获取 std::set.

的子集

目前,我正在将 100 个元素复制到临时集合并将其传递给函数。

struct MyClass
{
    // Class having considerably large size instance
};

// Library function that processes set having only 100 elements at a time
void ProcessSet (std::set<MyClass>* ptrMyClassObjectsSet);

void FunctionToProcessLargeSet (std::set<MyClass>& MyClassObjSet)
{
    std::set<MyClass> MyClass100ObjSet;

    // Cannot pass MyClassObject as it is to ProcessSet as it might have large number of elements
    // So create set of 100 elements and pass it to the function
    std::set<MyClass>::iterator it;
    for (it = MyClassObjSet.begin(); it != MyClassObjSet.end(); ++it)
    {
        MyClass100ObjSet.insert (*it);

        if (MyClass100ObjSet.size() == 100)
        {
            ProcessSet (&MyClass100ObjSet);
            MyClass100ObjSet.clear();
        }
    }

    // Prrocess remaining elments
    ProcessSet (&MyClass100ObjSet);
    MyClass100ObjSet.clear();
}

但这会影响性能。谁能建议更好的方法来做到这一点?

嗯,这听起来像是一个糟糕的库设计,但如果你必须使用现有的东西,那么:

  • 如果库 可以 接受一对迭代器 - 这是使用 std::advance
  • 的简单方法
  • 如果它是模板化的并且可以接受 std::set<T>,那么如果复制 T 很慢,将你的集合的一部分复制到 std::set<std::reference_wrapper<T>> 可能会执行得更好(参见 here 以了解没有复制已创建)
  • 如果它只接受std::set<ParticularObjectType>,我看不到复制数据的方法。

希望这对您有所帮助,

罗斯蒂斯拉夫。

因为看起来您不得不使用一个子集。我稍微调整了您的代码,我认为它对您来说可能更快。它仍然是一个 O(n) 操作,但是 for 循环中没有分支,这应该会提高性能。

void FunctionToProcessLargeSet(std::set<MyClass>& MyClassObjSet)
{
    int iteration = MyClassOgjSet.size() / 100; // get number of times we have collection of 100
    auto it = MyClassObjSet.begin();
    auto end = MyClassObjSet.begin();
    for (; iteration == 0; --iteration)
    {
        std::advance(end, 100); // move end 100 away
        std::set<MyClass> MyClass100ObjSet(it, std::advance(it, end));  // construct with iterator range
        std::advance(it, 100); // advace it to end pos
        ProcessSet(&MyClass100ObjSet); // process subset
    }
    if (MyClassOgjSet.size() % 100 != 0)  // get last subset
    {
        std::set<MyClass> MyClass100ObjSet(it, MyClassObjSet.end());
        // Prrocess remaining elments
        ProcessSet(&MyClass100ObjSet);
    }
}

如果这对你来说运行得更快,请告诉我。