Нарезка C-массива, создающего вектор C , сохраняя только 2 элемента каждые 3

#c #object-slicing

#c #нарезка объектов

Вопрос:

У меня есть C-массив, подобный этому:

 int X[]={0, 1, 2, 3, 4, 5, 6, 7, 8};
  

Мне нужно создать два stl-вектора из этого массива с помощью нарезки, возможно, с использованием наибольшего объема памяти и с возможностью создания менее глубоких копий.
Первый вектор Y должен содержать только 0 -й и первый элемент каждые три элемента, например, в этом случае этот новый вектор Y будет содержать

 std::vector<int> Y; // contains: [0,1,3,4,6,7]
  

и другой вектор Z должен содержать каждый 3-й элемент в исходном массиве:

 std::vector<int> Z; // contains [2,5,8]
  

Первое решение, основанное на циклах for с copy , заключается в следующем:

 vector<int> Y,Z;
for (int i=0; i<9;i =3)
{
    Y.push_back(*(X i));
    Y.push_back(*(X i 1));
    Z.push_back(*(X 2));
}
  

но я почти уверен, что с помощью пользовательских итераторов проблема может иметь более эффективное решение. Есть ли, в любом случае, какая-то другая более быстрая версия реализации представления маски в этом массиве, которая позволяет избежать создания копий?

Комментарии:

1. Какие-либо конкретные вопросы?

2. Я не думаю, что есть способ сделать это с помощью пользовательских итераторов без чрезмерной инженерии.

3. Я не понимаю, как пользовательские итераторы могли бы сделать ваш простой цикл for более «эффективным» (хотя вы могли бы использовать некоторые .reserve s) en.wikipedia.org/wiki/KISS_principle

4. Кроме использования reserve() , я сомневаюсь, что вы могли бы добиться гораздо большей эффективности.

5. @LightnessRacesinOrbit: разве «Упростить, а затем добавить легкости» не подходит вам лучше 🙂

Ответ №1:

Может быть, вы имеете в виду что-то вроде этого:

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

struct MyIndexing {
    int* original;
    MyIndexing(int* o) : original(o) {}
    intamp; getY(int index){ return original[0]; /* to be done... */ }
    intamp; getZ(int index){ return original[(index 1)*3 -1]; }
};

int main() {
    int X[]={0, 1, 2, 3, 4, 5, 6, 7, 8};
    MyIndexing mi(X);
    for (int i=0;i<3;i  ){ std::cout << mi.getZ(i) << " "; }
    return 0;
}
  

С принтами:

 2  5  8
  

Он не создает векторы, но в любом случае ваши требования немного противоречат друг другу. Либо вы избегаете копий, либо создаете новые векторы. Оба варианта невозможны.

Ответ №2:

Если вам НУЖНО создавать векторы, вы ДОЛЖНЫ сделать копию данных, поскольку данные векторов являются непрерывными.

Если вам не нужны векторы, вы могли бы создать 2 интерфейса (простите мою терминологию C #, но я думаю, что это применимо), один, который обеспечивал бы получение данных Y, другой, который предлагал бы данные X; реализация, расширяющая эти 2 интерфейса, может скрыть тот факт, что вашданные вообще находятся в векторе.

Комментарии:

1. Все фактически верно. Однако такой интерфейс был бы довольно неэффективным для использования в большинстве сценариев, которые я себе представляю. Тем не менее, похоже, что это то, что запрашивает OP (сейчас), после редактирования. Однако вы на самом деле не предоставили решения