C++ || How To Split & Batch An Array/Vector/Container Into Smaller Sub-Lists Of N Size Using C++
The following is a module with functions which demonstrates how to split/batch an array/vector/container into smaller sublists of n size using C++.
The function demonstrated on this page is a template, so it should work on containers of any type. It uses a simple for loop to group items into batches.
1. Partition – Integer Array
The example below demonstrates the use of ‘Utils::partition‘ to group an integer array into batches.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// Partition - Integer Array // Declare numbers int numbers[] = { 1987, 19, 22, 2009, 2019, 1991, 28, 31 }; // Get array size int size = sizeof(numbers) / sizeof(numbers[0]); // Split into sub groups auto numbersPartition = Utils::partition(numbers, numbers + size, 3); // Display grouped batches for (unsigned batchCount = 0; batchCount < numbersPartition.size(); ++batchCount) { auto batch = numbersPartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item << std::endl; } } // expected output: /* Batch #1 Item: 1987 Item: 19 Item: 22 Batch #2 Item: 2009 Item: 2019 Item: 1991 Batch #3 Item: 28 Item: 31 */ |
2. Partition – String Vector
The example below demonstrates the use of ‘Utils::partition‘ to group a string vector into batches.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Partition - String Vector // Declare data std::vector<std::string> names = { "Kenneth", "Jennifer", "Lynn", "Sole" }; // Split into sub groups auto namesPartition = Utils::partition(names.begin(), names.end(), 2); // Display grouped batches for (unsigned batchCount = 0; batchCount < namesPartition.size(); ++batchCount) { auto batch = namesPartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item << std::endl; } } // expected output: /* Batch #1 Item: Kenneth Item: Jennifer Batch #2 Item: Lynn Item: Sole */ |
3. Partition – Custom Object Vector
The example below demonstrates the use of ‘Utils::partition‘ to group a custom object vector into batches.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// Partition - Custom Object Vector // Declare object struct Person { int id; std::string name; }; // Declare data std::vector<Person> people = { {31, "Kenneth"}, {28, "Jennifer"}, {87, "Lynn"}, {91, "Sole"}, {22, "Kenneth"}, {19, "Jennifer"} }; // Split into sub groups auto peoplePartition = Utils::partition(people.begin(), people.end(), 4); // Display grouped batches for (unsigned batchCount = 0; batchCount < peoplePartition.size(); ++batchCount) { auto batch = peoplePartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item.id << " - " << item.name << std::endl; } } // expected output: /* Batch #1 Item: 31 - Kenneth Item: 28 - Jennifer Item: 87 - Lynn Item: 91 - Sole Batch #2 Item: 22 - Kenneth Item: 19 - Jennifer */ |
4. Utils Namespace
The following is the Utils Namespace. Include this in your project to start using!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// ============================================================================ // Author: Kenneth Perkins // Date: Feb 24, 2021 // Taken From: http://programmingnotes.org/ // File: Utils.h // Description: Handles general utility functions // ============================================================================ #pragma once #include <vector> #include <iterator> namespace Utils { /** * FUNCTION: partition * USE: Breaks a sequence into smaller sub-lists of a specified size * in the given range [first, last) * @param first: The first position of the sequence * @param last: The last position of the sequence * @param size: The maximum size of each sub-list * @return: A container of the smaller sub-lists of the specified size */ template<typename InputIt, typename T = typename std::iterator_traits<InputIt>::value_type> std::vector<std::vector<T>> partition(InputIt first, InputIt last, unsigned size) { std::vector<std::vector<T>> result; std::vector<T>* batch{}; for (unsigned index = 0, row = 0; first != last; ++first, ++index) { if ((index % size) == 0) { result.resize(++row); batch = &result.back(); batch->reserve(size); } batch->push_back(*first); } return result; } }// http://programmingnotes.org/ |
5. More Examples
Below are more examples demonstrating the use of the ‘Utils‘ Namespace. Don’t forget to include the module when running the examples!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
// ============================================================================ // Author: Kenneth Perkins // Date: Feb 24, 2021 // Taken From: http://programmingnotes.org/ // File: program.cpp // Description: The following demonstrates the use of the Utils Namespace // ============================================================================ #include <iostream> #include <string> #include <exception> #include <vector> #include "Utils.h" // Declare object struct Person { int id; std::string name; }; void display(const std::string& message); int main() { try { // Declare numbers int numbers[] = { 1987, 19, 22, 2009, 2019, 1991, 28, 31 }; // Get array size int size = sizeof(numbers) / sizeof(numbers[0]); // Split into sub groups auto numbersPartition = Utils::partition(numbers, numbers + size, 3); // Display grouped batches for (unsigned batchCount = 0; batchCount < numbersPartition.size(); ++batchCount) { auto batch = numbersPartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item << std::endl; } } display(""); // Declare data std::vector<std::string> names = { "Kenneth", "Jennifer", "Lynn", "Sole" }; // Split into sub groups auto namesPartition = Utils::partition(names.begin(), names.end(), 2); // Display grouped batches for (unsigned batchCount = 0; batchCount < namesPartition.size(); ++batchCount) { auto batch = namesPartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item << std::endl; } } display(""); // Declare data std::vector<Person> people = { {31, "Kenneth"}, {28, "Jennifer"}, {87, "Lynn"}, {91, "Sole"}, {22, "Kenneth"}, {19, "Jennifer"} }; // Split into sub groups auto peoplePartition = Utils::partition(people.begin(), people.end(), 4); // Display grouped batches for (unsigned batchCount = 0; batchCount < peoplePartition.size(); ++batchCount) { auto batch = peoplePartition[batchCount]; std::cout << "Batch #" << batchCount + 1 << std::endl; for (const auto& item : batch) { std::cout << " Item: " << item.id << " - " << item.name << std::endl; } } } catch (std::exception& e) { display("\nAn error occurred: " + std::string(e.what())); } std::cin.get(); return 0; } void display(const std::string& message) { std::cout << message << std::endl; }// http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Leave a Reply