Нарезка вектора - PullRequest
30 голосов
/ 10 июля 2009

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

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;
}

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

Ответы [ 6 ]

28 голосов
/ 10 июля 2009

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

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 должна позволять вам представлять пары итераторов как один объект, но приведенный выше канонический способ сделать это.

9 голосов
/ 04 декабря 2013

Я выучил Python, прежде чем я изучил C ++. Мне было интересно, предлагает ли C ++ нарезку векторов, например нарезку в списках 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}

5 голосов
/ 14 августа 2015

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

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

Пример использования:

#include <iostream>
#include <vector>

int main ()
{
    std::vector<int> indexes{3, 6, 9};

    for( auto index : indexes )
    {
        int slice = 3;
        std::vector<int> bar{1, 2, 3, 4, 5, 6, 7, 8, 9};
        std::vector<int>( bar.begin() + index - slice, bar.begin() + index ).swap(bar);

        std::cout << "bar index " << index << " contains:";
        for (unsigned i=0; i<bar.size(); i++)
            std::cout << ' ' << bar[i];
        std::cout << '\n';
    }

    return 0;
}

Выходы:

bar index 3 contains: 1 2 3
bar index 6 contains: 4 5 6
bar index 9 contains: 7 8 9
2 голосов
/ 10 июля 2014

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

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

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

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

2 голосов
/ 12 июля 2009

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

2 голосов
/ 10 июля 2009

Вы можете представить эти "кусочки" с помощью пары итераторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...