the_martian
the_martian

Reputation: 634

Split an array at a specific value C++

Say I have an array like this:

int arr [9] = {2,1,5,8,9,4,10,15,20}

How can you split the array at a certain value threshold? So say int 8 is our splitting value, the end result would be two separate arrays (or a 2d array if you want to give that a shot) that in this example would be arr1 [4] = {1,2,4,5} and arr2 [5] = {8,9,10,15,20}. arr1 stores all the values in arr that are below 8 and and arr2 stores all the values in arr that are 8 and above.

I haven't been able to locate sufficient documentation or examples of this being done and I think array manipulation and splitting is worth having examples of.

Upvotes: 3

Views: 2063

Answers (3)

the_martian
the_martian

Reputation: 634

I'm working on a solution with loops. This is a work in progress. Let me know what you think.

void splitarr(int arr[], int length) {
    int accu = 0;
    int accu2 = 0;
    int splitter = rand() % 20;
    for (int i = 0; i < length; i++) {
        if (i != splitter) {
            accu++;
        }
    }
    int arr1[accu];
    for (int i = 0; i < length; i++) {
        if (i != splitter) {
            arr1[i] = i;
        }

    }

    for (int i = 0; i < length; i++) {
        if (i == splitter) {
            accu2++;
        }
    }
    int arr2[accu2];
    for (int i = 0; i < length; i++) {
        if (i == splitter) {
            arr2[i] = i;
        }

    }
}

Upvotes: 0

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

Use std::partition, or if you want to maintain the relative order and not sort the data, std::stable_partition.

    #include <algorithm>
    #include <iostream>
    #include <vector>

    int main()
    {
        int pivot = 8;
        int arr [9] = {2,1,5,8,9,4,10,15,20};

        // get partition point  
        int *pt = std::stable_partition(arr, std::end(arr), [&](int n) {return n < pivot;});

        // create two vectors consisting of left and right hand side
        // of partition
        std::vector<int> a1(arr, pt);
        std::vector<int> a2(pt, std::end(arr));

        // output results
        for (auto& i : a1)
            std::cout << i << " ";
        std::cout << '\n';
        for (auto& i : a2)
            std::cout << i << " ";
    }

Live Example

Upvotes: 3

ZivS
ZivS

Reputation: 2124

If you can use C++11 then this is one way of using the standard library:

Using a partition_point: (edited the example from the link)

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <vector>

int main()
{
    std::array<int, 9> v = {2,1,5,8,9,4,10,15,20};

    auto is_lower_than_8 = [](int i){ return i < 8; };
    std::partition(v.begin(), v.end(), is_lower_than_8 );

    auto p = std::partition_point(v.begin(), v.end(), is_lower_than_8 );

    std::cout << "Before partition:\n    ";
    std::vector<int> p1(v.begin(), p);
    std::sort(p1.begin(), p1.end());
    std::copy(p1.begin(), p1.end(), std::ostream_iterator<int>(std::cout, " "));

    std::cout << "\nAfter partition:\n    ";
    std::vector<int> p2(p, v.end());
    std::sort(p2.begin(), p2.end());
    std::copy(p2.begin(), p2.end(), std::ostream_iterator<int>(std::cout, " "));
}

Which prints:

Before partition:
    1 2 4 5 
After partition:
    8 9 10 15 20

Upvotes: 2

Related Questions