Как разбить вектор на n "почти равных" частей
У меня есть проблема, что я хотел бы объединить большое количество изображений с помощью ImageMagick convert.exe, но в Windows у меня есть ограничение на длину строки 8192 байта.
Мое решение состоит в том, чтобы разделить задачу на меньшую подзадачу, запустить ее и выполнить конечную задачу, которая объединяет их вместе.
Моя идея - написать функцию, которая берет вектор изображений и целое число и разбивает вектор на n суб-вектора, все имеющие "почти равные" части.
Так, например, если бы я хотел разделить 11 на 3 группы, это было бы 4-4-3.
Можете ли вы рассказать мне, как я могу это сделать на С++? Я имею в виду, чтобы написать функцию
split_vec( const vector<image> &images, int split )
который выполняет расщепление?
Кроме того, можете ли вы рассказать мне, что является наиболее эффективным способом сделать , если мне не нужно создавать новые векторы, просто перебирайте их под частями? Как функция std::substr
с std::string
?
Примечание. Я уже использую Boost в проекте, поэтому, если для этого есть хороший инструмент для Boost, он идеально подходит для меня.
Ответы
Ответ 1
Чтобы получить базовое число для размера каждой части, просто разделите общее количество на количество частей: 11/3 = 3. Очевидно, что некоторые из частей должны быть больше, чем для получения правильной суммы, но что остальная часть: 11% 3 = 2. Итак, теперь вы знаете, что 2 части будут размером 3 + 1, а все оставшееся будет 3.
Ответ 2
Вот мое решение:
template<typename T>
std::vector<std::vector<T>> SplitVector(const std::vector<T>& vec, size_t n)
{
std::vector<std::vector<T>> outVec;
size_t length = vec.size() / n;
size_t remain = vec.size() % n;
size_t begin = 0;
size_t end = 0;
for (size_t i = 0; i < std::min(n, vec.size()); ++i)
{
end += (remain > 0) ? (length + !!(remain--)) : length;
outVec.push_back(std::vector<T>(vec.begin() + begin, vec.begin() + end));
begin = end;
}
return outVec;
}
Ответ 3
Задумывались ли вы об использовании программы xargs
. Это может быть решение высокого уровня проблемы.
Ответ 4
Вам не нужно создавать новые под-векторы, используйте что-то вроде следующего:
size_t ProcessSubVec(const vector<Image>& images, size_t begin, size_t end)
{
// your processing logic
}
void SplitVec(const vector<Image>& images, int cnt)
{
size_t SubVecLen = images.size() / cnt,
LeftOvers = images.size() % cnt,
i = 0;
// Split into "cnt" partitions
while(i < images.size())
i += ProcessSubVec(images, i, i + SubVecLen + (LeftOvers-- == 0 ? 0 : 1));
}
Надеюсь, что это поможет.
Ответ 5
CreateProcess имеет ограничение в 32 КБ
Или, если вы хотите пройти через оболочку,
vec::const_iterator i = vec .begin ();
vec::const_iterator j = i + stride;
while (j < vec .end ()) {
do_range (i, j);
i = j;
j += stride;
}
do_range (i, vec .end ());
Ответ 6
Вы можете использовать iterators
для итерации по частям проблемы. Использование итераторов аналогично указателям на элементы vector
То, что вы хотите на изображениях, может быть реализовано как функция
using namespace std;
void do_some_work(vector<image>::iterator begin, vector<image>::iterator end) {
vector<image>::iterator i = begin ;
while(i != end) {
// do something using *i , which will be of type image
++i ;
}
}