简体   繁体   中英

Best way to split a vector into two smaller arrays?

What I'm trying to do:

I am trying to split a vector into two separate arrays. The current int vector contains an element per line in a text file. The text file is a list of random integers.

How I'm planning to do it:

My current idea is to create two regular int arrays, then iterate over the entire vector and copy n/2 elements to each of the arrays.

What I would like to know:

What is the most elegant way of accomplishing my task? I have a feeling that I can do this without iterating over the vector multiple times.

Code:

#include <vector>
#include <fstream>
#include <iterator>
#include <iostream>
using namespace std;

vector<int> ifstream_lines(ifstream& fs)
{
  vector<int> out;
  int temp;
  while(fs >> temp)
  {
    out.push_back(temp);
  }
  return out;
}

vector<int> MergeSort(vector<int>& lines)
{
  int split = lines.size() / 2;
  int arrayA[split];
  int arrayB[split];
}

int main(void) 
{
  ifstream fs("textfile.txt");
  vector<int> lines;
  lines = ifstream_lines(fs);

  return 0;
}

Thank you :)

Use iterators.

std::vector<int> lines;
// fill
std::size_t const half_size = lines.size() / 2;
std::vector<int> split_lo(lines.begin(), lines.begin() + half_size);
std::vector<int> split_hi(lines.begin() + half_size, lines.end());

Since iterator ranges represent half open ranges [begin, end) , you don't need to add 1 to the second begin iterator: lines.begin() + half_size isn't copied to the first vector.


Note that things like

int split = lines.size() / 2;
int arrayA[split];
int arrayB[split];

Are not standard C++ (and as such not portable). These are so-called variable-length arrays (VLAs for short) and are a C99 thing. Some compilers have them as an extension while compiling C++ code (GCC, Clang). Always compile with -pedantic to get a warning. These VLAs act funky for non-POD types and aren't generally useful, since you can't even return them.

If you can't use code from Xeo answer due to strict compiler rules or you want more generic way, try std::advance :

#include <vector>
#include <iterator>

size_t middle = input.size()/2;
std::vector<int>::const_iterator middleIter(input.cbegin());
std::advance(middleIter, middle);

std::vector<int> leftHalf(input.begin(), middleIter);
std::vector<int> rightHalf(middleIter, input.end());

If you only need a reference to the numbers without manipulating them, then you can do:

int *array_1 = &lines[0];
int *array_2 = &lines[lines.size() / 2];

array_1 and array_2 are, actually, pointers to the start and middle of the vector. This works since STL guarantees that vectors store their elements within a continuous memory. Note that referring to lines.begin() can't be used for this.

Solution to split vector to variable count parts using iterator.

#include <iostream>
#include <vector>

int main()
{
   // Original vector of data
   std::vector<double> mainVec{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0};
   // Result vectors
   std::vector<std::vector<double>> subVecs{};
   // Start iterator
   auto itr = mainVec.begin();
   // Variable to control size of non divided elements
   unsigned fullSize = mainVec.size();
   // To regulate count of parts
   unsigned partsCount = 4U;
   for(unsigned i = 0; i < partsCount; ++i)
   {
       // Variable controls the size of a part
       auto partSize = fullSize / (partsCount - i);
       fullSize -= partSize;
       // 
       subVecs.emplace_back(std::vector<double>{itr, itr+partSize});
       itr += partSize;
   }
   // Print out result
   for (const auto& elemOuter : subVecs)
   {
       std::cout << std::fixed;
       for (const auto& elemInner : elemOuter)
       {
           std::cout << elemInner << " ";
       }
       std::cout << "\n";
   }
}

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