简体   繁体   中英

Split vector into new smaller size vectors

Problem

I have vector V = {1,2,3,4,5,6,7,8,9,10,11} and suppose I want to create N new vectors from this large vector.

Example: N = 3 means it will split the vector by the largest available size ie 4-4-3
v1 = {1,2,3,4}
v2 = {5,6,7,8}
v3 = {9,10,11}

Code

std::vector<int> v;
for (int i = 1; i < 12; i++) v.push_back(i);   

// Function here to set boundaries ???
N = 3;
v.size()/N % N
//
std::vector<int> v1(v.begin(), v.begin()+3);
std::vector<int> v2(v.begin()+4, v.begin()+7);
std::vector<int> v3(v.begin()+8, v.begin()+11);

Want to Achieve

  1. Function that does automatic creation of the vectors by itself so I don't want to manually create v1,v2,v3 if it is possible.
  2. And how I can write the boundary checking algorithm?

You get get the i-th chunk of vec if you divide into n chunks like this:

template <typename T>
std::span<T> get_chunk(std::vector<T> const & vec, std::size_t n, std::size_t i)
{
  assert(i < n);
  std::size_t const q = vec.size() / n;
  std::size_t const r = vec.size() % n;
  
  auto begin = vec.begin() + i * q + std::min(i, r);
  auto end = vec.begin() + (i + 1) * q + std::min(i + 1, r);
  
  return std::span<T>(begin, end);
}

If you don't / can't use std::span , just replace it with std::vector or use begin and end -iterators directly.

Function that does automatic creation of the vectors by itself so I don't want to manually create v1,v2,v3 if it is possible.

What could be a data structure than can hold N number of objects? How about an array? But you might want the size to be determined at runtime. How could you create an array with runtime size? Use a vector, In conclusion. write a function that creates a vector of vectors.

Note that instead of having separate vectors, it might be more efficient to keep the original vector intact, and use a vector of std::span (prior to C++20 you can use a non-standard implementation of the same concept) pointing to the subranges.

A simple way is to build a vector of vector to collect the different arrays.

To control the boundaries, one possibility is first to calculate the maximum size of these arrays, and then to manage two indices, one ibegin corresponding to the beginning of a subarray, and one iend corresponding to the end of the same subarray.

Output:

1 2 3 4
5 6 7 8
9 10 11

Code:

#include <iostream>
#include <vector>

std::vector<std::vector<int>> split (const std::vector<int>& v, int Nsplit) {
    int n = v.size();
    int size_max = n / Nsplit + (n % Nsplit != 0);
    std::vector<std::vector<int>> split;
    for (int ibegin = 0; ibegin < n; ibegin += size_max) {
        int iend = ibegin + size_max;
        if (iend > n) iend = n;
        split.emplace_back (std::vector<int>(v.begin() + ibegin, v.begin() + iend));
    }
    return split;
}

int main() {
     std::vector<int>Arr = {1,2,3,4,5,6,7,8,9,10,11};
     int Nsplit = 3;
     auto ans = split (Arr, Nsplit);
     
    for (auto &v: ans) {
        for (auto& i: v) {
            std::cout << i << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM