2015-08-27 4 views
0

Я вызываю библиотечную функцию, которая принимает указатель на 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(); 
} 

Но это влияет на производительность. Может ли кто-нибудь предложить лучшие способы сделать это?

+2

Можете ли вы показать [mcve] того, что вы сейчас делаете? – NathanOliver

+0

Если библиотеке требуется серия небольших объектов 'std :: set', то это то, что вы должны создать. Тот факт, что они являются подмножествами чего-то другого, не кажется полезным. Не предлагает ли библиотека другой альтернативы? Являются ли они выделенными кучами объектами типа 'std :: string'? – Potatoswatter

+0

@Potatoswatter: Да объекты выделены в кучу. Я думал, что если бы это был массив, я бы передал «часть оригинального массива, просто указав индексы массива», но в случае std :: set я не могу этого сделать (или есть ли способ сделать это?) – Atul

ответ

1

Поскольку похоже, что вы заблокированы, чтобы использовать подмножество. Я немного изменил ваш код, и я думаю, что это может быть быстрее для вас. Он по-прежнему является операцией 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); 
    } 
} 

Сообщите мне, если это работает быстрее для вас.

1

Ну, это звучит как плохой дизайн библиотеки, но если вы должны работать с тем, что у вас есть то:

  • Если библиотека может принять пару итераторов - это легкий путь, используя std::advance
  • Если это шаблонный и может принимать std::set<T>, а затем скопировать часть вашего набора, чтобы std::set<std::reference_wrapper<T>> может работать лучше, если копирование T медленно (см here видеть, что копии не создаются)
  • Если он принимает только std::set<ParticularObjectType>, я не вижу способа копирования данных.

Надеется, что это помогает,

Ростислав.

+0

Большое спасибо ! Я буду оценивать эти параметры. – Atul