2011-07-28 73 views
13

我有,我想合併大量使用ImageMagick的CONVERT.EXE圖像的問題,但在Windows下我有一個8192字節長的命令行限制。如何將矢量分成N「幾乎相等」的部分

我的這個解決方案是將任務分割成更小的子任務,運行它們,並做它結合在一起最後的任務。

我的想法是寫一個函數,該函數的圖像和一個整數的向量,並分割所述載體引入n個子矢量全部具有「幾乎相等」的部分。

因此,舉例來說,如果我想11分成3組,這將是4-4-3。

你能告訴我,我怎麼能做到這一點在C++?我的意思是,寫一個函數

split_vec(const vector<image> &images, int split) 

哪個分裂?

另外,你能告訴我什麼是最有效的方法嗎如果我不需要創建新的向量,只需遍歷子部分?像std::substr功能與std::string

注:我已經使用了升壓的項目,所以如果在加速這一一些很好的工具,然後它非常適合我。

回答

10

要獲得每個零件尺寸的基數,只需將總數除以零件數:11/3 = 3.顯然,某些零件需要比獲得適當總量,但是這只是剩餘的11%3 = 2,所以,現在你知道了份2的大小爲3 + 1,不管剩下的過會3

+0

謝謝,這裏是我想出的:double loop = number/parts; for(int i = 0; i zsero

+0

@zsero,如果'number'和'parts'都是整數,則在進行除法之前,需要將1轉換爲2。你也需要擔心舍入誤差,有些情況下,當你轉換回整數時,你可能會遇到一個錯誤的錯誤。 –

+0

其實我在函數定義中使用了雙精度,而在起始和結束時使用了round()函數。你認爲使用round()函數時可能會出現舍入誤差嗎? (我使用stringstream來輪) – zsero

0

CreateProcess has a 32kb limit

或者,如果您想要通過外殼去,

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()); 
0

您可以使用iterators來遍歷問題的子部分。你想上的圖像也可以被實現爲一個功能

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 ; 
    } 
} 
1

你有沒有想過使用xargs程序什麼的迭代器用法類似於指針的vector

元素。這可能是該問題的高級解決方案。

+0

他使用* Windows * – spraff

+2

我一直在Windows機器上使用「unix」實用程序。結帳:unxutils.sf.net和/或www.cygwin.com – Mike

+0

感謝您的提示,儘管我恐怕這不會幫助他在*別人的*計算機上運行代碼:-P – spraff

1

您不必創建新的子向量,使用類似以下內容:

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)); 
} 

希望這有助於。

+0

Brandon ProcessSubVec應該返回什麼?我不明白這一點。 –

4

這裏是我的解決方案:

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; 
} 
+1

使用Yury的例子:https://onlinegdb.com/rkYRK-raW – CodeGuyRoss

0

你可以創建一個返回一個std ::矢量<的std ::矢量> 和接收你想分裂矢量模板,並且劃分數。 使用for和iterator是很容易的。

#include <iostream> 
#include <iomanip> 
#include <vector> 
#include <algorithm> 
#include <numeric> 

template<typename T> 
std::vector< std::vector<T> > split(std::vector<T> vec, uint64_t n) { 
    std::vector< std::vector<T> > vec_of_vecs(n); 

    uint64_t quotient = vec.size()/n; 
    uint64_t reminder = vec.size() % n; 
    uint64_t first = 0; 
    uint64_t last; 
    for (uint64_t i = 0; i < n; ++i) { 
    if (i < reminder) { 
     last = first + quotient + 1; 
     vec_of_vecs[i] = std::vector<T>(vec.begin() + first, vec.begin() + last); 
     first = last; 
    } 
    else if (i != n - 1) { 
    last = first + quotient; 
    vec_of_vecs[i] = std::vector<T>(vec.begin() + first, vec.begin() + last); 
    first = last; 
    } 
    else 
    vec_of_vecs[i] = std::vector<T>(vec.begin() + first, vec.end()); 
} 

return vec_of_vecs; 
} 

#define ONE_DIMENSION 11 
#define SPLITS 3 

int main(void) 
{ 
    std::vector<uint64_t> vector(ONE_DIMENSION); 
    std::iota(std::begin(vector), std::end(vector), 1); 

    std::vector<std::vector<uint64_t>> vecs(SPLITS); 
    vecs = split(vector, SPLITS); 

    for (uint64_t m = 0; m < vecs.size(); ++m) { 
    for (auto i : vecs[m]) 
     std::cout << std::setw(3) << i << " "; 
    std::cout << std::endl; 
    } 


    return 0; 
}