Reputation: 710
Using C++, I want to create an array which only contains the first n elements of another array. Like so in Scala: val arrayTwo = arrayOne.take(n)
I know I can use a loop and copy the elements one by one, but this is much more complicated than necessary, it takes unnecessary space, and that makes it less readable. Is there a simple, readable function to create a new array from the first n elements of a given previous array? Also I would like to reuse a function from somewhere, rather than writing one on my own, because I don't want to pollute the namespace unnecessarily. Performance doesn't matter as long as it takes O(n).
std::copy_n looked like it, but I can't get it to work because std::back_inserter for some reason doesn't accept my array (I also tried with a pointer instead of array, still not working).
This is my best attempt so far.
#include <iostream>
#include <utility>
#include <algorithm>
#include <vector>
#include <iterator>
#include <stdio.h>
#include <math.h>
using std::pair;
int main() {
pair<double, double> fabricatedPoints[] = { { 15.3, 12.9 }, { 88.6, 56.0 },
{ 0.4, 18.0 }, { 5.0, 3.13 }, { 2.46, 86.01 } };
pair<double, double> points[] = {};
std::copy_n(std::begin(fabricatedPoints), 3, std::back_inserter(points));
}
It can be done either with copy_n, or by other means, I don't mind as long as it is readable. If there exists no readable solution in libraries (not necessarily the standard libraries - it could also be Boost or something, as long as it's a widely used library), then I will accept an answer which provides convincing evidence of no such solution existing.
Upvotes: 10
Views: 24489
Reputation: 12751
From C++20 ranges (#include <ranges>
)
Simply use take_view
//DATA
std::pair<double, double> fabricatedPoints[] = { { 15.3, 12.9 }, { 88.6, 56.0 },
{ 0.4, 18.0 }, { 5.0, 3.13 }, { 2.46, 86.01 } };
//USE take_view
auto points = std::ranges::take_view(fabricatedPoints, 2);
//TEST THEM
for (auto p : points)
{
std::cout << p.first << " " << p.second << std::endl;;
}
Or using view adapters
//YOUR DATA
std::pair<double, double> fabricatedPoints[] = { { 15.3, 12.9 }, { 88.6, 56.0 },
{ 0.4, 18.0 }, { 5.0, 3.13 }, { 2.46, 86.01 } };
//GET FIRST TWO POINTS
auto points = std::views::all(fabricatedPoints) | std::views::take(2);
//TEST THEM
for (auto p : points)
{
std::cout << p.first << " " << p.second << std::endl;;
}
Upvotes: 2
Reputation: 129
I would use vector
for this
vector<int> vec1;
vector<int> vec2;
vector<int> merged;
//insert(where you want to start adding, from which index, to which index)
//in this case we are adding the first to n-th elements from vec1 to the last element of merged
merged.insert(merged.end(), vec1.begin(), vec1.begin() + n);
//here we are adding the m-th to n-th elements of vec2 to the first element of merged
merged.insert(merged.begin(), vec2.begin() + m, vec2.begin() + n);
Upvotes: 0
Reputation: 409166
You can't append to normal C-style arrays like points
(actually, I would be surprised if the declaration didn't generate compiler errors). Trying to append to a C-style array would write beyond the bounds, leading to undefined behavior (and here too I'm surprised that std::back_inserter
would compile when passed a C-style array).
Instead use a std::vector
.
Upvotes: 1
Reputation: 179402
If you were using vectors (and you should, you're using C++), you could just do this:
using std::vector;
vector<pair<double, double>> a{ {15.3, 12.9}, ...};
vector<pair<double, double>> b(a.begin(), a.begin() + 3);
For arrays you will have to make sure to preallocate the array to the right size:
pair<double, double> b[3];
std::copy_n(a, 3, b);
Upvotes: 14