Подтвердить что ты не робот

Как разбить вектор на 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, он идеально подходит для меня.

4b9b3361

Ответ 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 ;
    }
}