Подтвердить что ты не робот

Нарезка вектора

У меня есть std::vector. Я хочу создать итераторы, представляющие срез этого вектора. Как мне это сделать? В псевдо С++:

class InterestingType;

void doSomething(slice& s) {
    for (slice::iterator i = s.begin(); i != s.end(); ++i) {
       std::cout << *i << endl;
    }
}
int main() {
   std::vector v();
   for (int i= 0; i < 10; ++i) { v.push_back(i); }
   slice slice1 = slice(v, 1, 5);
   slice slice2 = slice(v, 2, 4);
   doSomething(slice1);
   doSomething(slice2);
   return 0;
}

Я бы предпочел не копировать элементы в новую структуру данных.

4b9b3361

Ответ 1

Вы просто используете пару итераторов:

typedef std::vector<int>::iterator vec_iter;

void doSomething(vec_iter first, vec_iter last) {
    for (vec_iter cur = first; cur != last; ++cur) {
       std::cout << *cur << endl;
    }
}

int main() {
   std::vector v();
   for (int i= 0; i < 10; ++i) { v.push_back(i); }

   doSomething(v.begin() + 1, v.begin() + 5);
   doSomething(v.begin() + 2, v.begin() + 4);
   return 0;
}

В качестве альтернативы библиотека Boost.Range должна позволять вам представлять пары итераторов как один объект, но выше это канонический способ сделать это.

Ответ 2

Я изучил Python, прежде чем научился С++. Я задавался вопросом, предложил ли С++ срез векторов, таких как нарезка в списках Python. Потребовалось пару минут, чтобы написать эту функцию, которая позволяет срезать вектор, аналогичный тому, как это делается на Python.

vector<int> slice(const vector<int>& v, int start=0, int end=-1) {
    int oldlen = v.size();
    int newlen;

    if (end == -1 or end >= oldlen){
        newlen = oldlen-start;
    } else {
        newlen = end-start;
    }

    vector<int> nv(newlen);

    for (int i=0; i<newlen; i++) {
        nv[i] = v[start+i];
    }
    return nv;
}

Использование:

vector<int> newvector = slice(vector_variable, start_index, end_index);

Элемент start_index будет включен в срез, тогда как end_index не будет включен.

Пример:

Для вектора v1, как {1,3,5,7,9}

slice (v1,2,4) возвращает {5,7}

Ответ 3

Взято из здесь:

std::vector<myvector::value_type>(myvector.begin()+start, myvector.begin()+end).swap(myvector);

Ответ 4

Как говорили другие, вы можете представить "срез" как пару итераторов. Если вы хотите использовать Boost, вы можете использовать концепцию диапазона. Тогда вы будете иметь даже функции begin()/end(), доступные, и вся эта вещь выглядит как контейнер.

Ответ 5

использовать адаптеры диапазона усиления. они lazy:

operator |() используется для ленивого добавления нового поведения и никогда не изменяет его левый аргумент.

boost::for_each(v|sliced(1,5)|transformed(doSomething));

doSomething должен принимать диапазон ввода. простая (может быть lambda) обертка будет исправлять это.

Ответ 6

Вы можете представить эти "срезы" с парой итераторов.