Как удалить каждый третий элемент
От: ShootNik  
Дата: 14.03.06 12:07
Оценка:
void main()
{
    std::vector<short> s;

    s.push_back(0);
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(2);
    s.push_back(5);
 }
Re: Как удалить каждый третий элемент
От: ekamaloff Великобритания  
Дата: 14.03.06 12:16
Оценка: 1 (1) +1
Здравствуйте, ShootNik, Вы писали:


for(vector<short>::size_type i = 2; i < s.size(); i+= 2)
{
    s.erase(s.begin() + i);
}
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[2]: Как удалить каждый третий элемент
От: saddva  
Дата: 14.03.06 12:28
Оценка: -1
Здравствуйте, ekamaloff, Вы писали:

E>Здравствуйте, ShootNik, Вы писали:



E>
E>for(vector<short>::size_type i = 2; i < s.size(); i+= 2)
E>{
E>    s.erase(s.begin() + i);
E>}
E>


Только правильнее:

vector<short>::size_type size = s.size();

for(vector<short>::size_type i = 2; i < size; i+= 2)
{
s.erase(s.begin() + i);
}
Re[3]: Как удалить каждый третий элемент
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 14.03.06 12:30
Оценка: +1
Здравствуйте, saddva, Вы писали:
S>Только правильнее:

S>vector<short>::size_type size = s.size();


S>for(vector<short>::size_type i = 2; i < size; i+= 2)

S>{
S> s.erase(s.begin() + i);
S>}

Не-а... выход за гранииы Вам обеспечен.. erase уменьшает кол-во элементов в массиве...
Re[2]: Как удалить каждый третий элемент
От: _DAle_ Беларусь  
Дата: 14.03.06 14:11
Оценка: 3 (1) +1
Здравствуйте, ekamaloff, Вы писали:

E>Здравствуйте, ShootNik, Вы писали:



E>
E>for(vector<short>::size_type i = 2; i < s.size(); i+= 2)
E>{
E>    s.erase(s.begin() + i);
E>}
E>


Если квадратичная сложность не нравится, то можно вот так
    int a[] = {1,2,3,4,5,6,7,8,9};
    vector<int> v(a, a+sizeof(a)/sizeof(a[0]));
    for (int i = 0; i < v.size(); ++i)
    {
        v[i-(i/3)] = v[i];
    }
    v.resize(v.size()-v.size()/3);
    copy(v.begin(), v.end(), ostream_iterator<int>(cout," "));
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[3]: Как удалить каждый третий элемент
От: srggal Украина  
Дата: 14.03.06 14:42
Оценка: +1
Здравствуйте, saddva, Вы писали:

Мои 5копеек:

struct Func
{
    Func()
        :    i(0)
    {
    }

    bool operator()(int )
    {
        return ++i % 3 == 0;
    }
private:
    int    i;
};

int main()
{
    typedef std::vector<int> vec_type;

    vec_type        v;
    for (int i=0; i<10; ++i)
    {
        v.push_back( i );
    }

    v.erase (
            remove_if( v.begin(), v.end(), Func() ), 
            v.end( ) 
        );

    std::copy(
            v.begin(),
            v.end(),
            std::ostream_iterator<int>( cout, "\n" )
        );

    return 0;
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Как удалить каждый третий элемент
От: ekamaloff Великобритания  
Дата: 14.03.06 14:48
Оценка:
Здравствуйте, srggal, Вы писали:

Ага, и сделать его еще чуть-чуть универсальней :

S>
S>struct Func
S>{
S>    Func(unsigned int f)
S>        :    i(0), factor(f)
S>    {
S>    }

S>    bool operator()(int )
S>    {
S>        return ++i % factor == 0;
S>    }
S>private:
S>    int    i;
S>    usnigned int    factor;
S>};

S>int main()
S>{
S>    typedef std::vector<int> vec_type;

S>    vec_type        v;
S>    for (int i=0; i<10; ++i)
S>    {
S>        v.push_back( i );
S>    }

S>    v.erase (
S>            remove_if( v.begin(), v.end(), Func(3) ), 
S>            v.end( ) 
S>        );

S>    std::copy(
S>            v.begin(),
S>            v.end(),
S>            std::ostream_iterator<int>( cout, "\n" )
S>        );

S>    return 0;
S>}
S>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[4]: Как удалить каждый третий элемент
От: HiSH Россия http://m0riarty.ya.ru
Дата: 14.03.06 14:54
Оценка: 5 (1)
Здравствуйте, srggal, Вы писали:

S>Мои 5копеек:


S>
S>struct Func
S>{
S>    Func()
S>        :    i(0)
S>    {
S>    }

S>    bool operator()(int )
S>    {
S>        return ++i % 3 == 0;
S>    }
S>private:
S>    int    i;
S>};

S>


Уже прямо боюсь что-то говорить Поэтому просто спрошу — а разве не рекомендуется делать функторы stateless, т. к. в алгоритмах они могут копироватьсся? Этот пример работет, т. к. функтор, с которого была снята копия больше не используется — такое поведение где-то (в Стандарте) оговаривается?
ЗЫ. Если i сделать статическим членом, тоже, ИМХО, не поможет — нет гарантии, что функтор не будет применен к какому-то объекту дважды.
... << RSDN@Home 1.1.4 stable SR1 rev. 568 with Алиса — Сумерки>>
Re[4]: Как удалить каждый третий элемент
От: _DAle_ Беларусь  
Дата: 14.03.06 14:57
Оценка: +2
Здравствуйте, srggal, Вы писали:

S>Здравствуйте, saddva, Вы писали:


S>Мои 5копеек:


На эти 5 копеек есть цитата.

Stateful predicates may seem useful, but they are explicitly not very useful with the C++ standard library and its algorithms, and that is intentional. In particular, stateful predicates can only be useful if:

The predicate is not copied: The standard algorithms make no such guarantee, and in fact assume that predicates are safely copyable.

The predicate is applied in a documented deterministic order: The standard algorithms generally make no guarantee about the order in which the predicate will be applied to the elements in the range. In the absence of guarantees about the order in which objects will be visited, operations like "flag the third element" (see Examples) make little sense, because which element will be visited "third" is not well-defined.

(с) C++ Coding Standards: 101 Rules, Guidelines, and Best Practices
By Herb Sutter, Andrei Alexandrescu


Этот код непереносим. В некоторых версиях STL он работать не будет. И есть подозрение, что во многих версиях.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[5]: Как удалить каждый третий элемент
От: HiSH Россия http://m0riarty.ya.ru
Дата: 14.03.06 15:01
Оценка:
Здравствуйте, HiSH, Вы писали:

HSH>Уже прямо боюсь что-то говорить Поэтому просто спрошу — а разве не рекомендуется делать функторы stateless, т. к. в алгоритмах они могут копироватьсся? Этот пример работет, т. к. функтор, с которого была снята копия больше не используется — такое поведение где-то (в Стандарте) оговаривается?

HSH>ЗЫ. Если i сделать статическим членом, тоже, ИМХО, не поможет — нет гарантии, что функтор не будет применен к какому-то объекту дважды.

Совсем забыл — или использовать передачу функтора по ссылке:
    v.erase (
            remove_if<vector<int>::iterator, vector<int>::iterator, Func&>( v.begin(), v.end(), Func() ), 
            v.end( ) 
        );
... << RSDN@Home 1.1.4 stable SR1 rev. 568 with Алиса — Пасынок звезд>>
Re[5]: Как удалить каждый третий элемент
От: srggal Украина  
Дата: 14.03.06 15:05
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>Здравствуйте, srggal, Вы писали:


E>Ага, и сделать его еще чуть-чуть универсальней :

Это не универсальность, вот если сделать так:

S>>
template< typename T >
S>>struct Func
    :    public std::unary_function< T, bool >
S>>{
S>>    Func(unsigned int f)
S>>        :    i(0), factor(f)
S>>    {
S>>    }

S>>    bool operator()(const T& )
S>>    {
S>>        return ++i % factor == 0;
S>>    }
S>>private:
S>>    int    i;
S>>    usnigned int    factor;
S>>};

S>>


Но задачу полностью решал приведенный мной код. Про универсальность условий не было, и я её не делал специально.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Как удалить каждый третий элемент
От: srggal Украина  
Дата: 14.03.06 15:17
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Здравствуйте, srggal, Вы писали:


S>>Здравствуйте, saddva, Вы писали:


S>>Мои 5копеек:


_DA>На эти 5 копеек есть цитата.

Ок, если не затруднит, возникла пара вопросов.

_DA>[q]Stateful predicates may seem useful, but they are explicitly not very useful with the C++ standard library and its algorithms, and that is intentional. In particular, stateful predicates can only be useful if:


_DA>The predicate is not copied: The standard algorithms make no such guarantee, and in fact assume that predicates are safely copyable.

Чем в конкретном случае копирование может помещать ?

_DA>The predicate is applied in a documented deterministic order: The standard algorithms generally make no guarantee about the order in which the predicate will be applied to the elements in the range. In the absence of guarantees about the order in which objects will be visited, operations like "flag the third element" (see Examples) make little sense, because which element will be visited "third" is not well-defined.

Задумался, вроде как в нашем конкретном случае должно все работать в порядке обхода итераторов, но в стандарте пока ничего не нашел.
Честно гря, как-то даже не задумывался, что последовательность применения предиката может оттличаться от последовательности итерирования.

Буду искать, если есть куда в стандарте, то ткните пальцем плз.

_DA>Этот код непереносим. В некоторых версиях STL он работать не будет. И есть подозрение, что во многих версиях.

У меня как раз обратное подозрение, что на многих = он будет работать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Как удалить каждый третий элемент
От: srggal Украина  
Дата: 14.03.06 15:21
Оценка:
S>Задумался, вроде как в нашем конкретном случае должно все работать в порядке обхода итераторов, но в стандарте пока ничего не нашел.
S>Честно гря, как-то даже не задумывался, что последовательность применения предиката может оттличаться от последовательности итерирования.

S>Буду искать, если есть куда в стандарте, то ткните пальцем плз.


Пока вот нашел следующее:

25.2.7/4 Notes: Stable: the relative order of the elements that are not removed is the same as their relative order in
the original range.


Т.е. раз Stable то вроде как это косвенно указывает но порядок применения предиката.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Как удалить каждый третий элемент
От: _DAle_ Беларусь  
Дата: 14.03.06 15:40
Оценка: 12 (1)
Здравствуйте, srggal, Вы писали:

_DA>>На эти 5 копеек есть цитата.

S>Ок, если не затруднит, возникла пара вопросов.

_DA>>[q]Stateful predicates may seem useful, but they are explicitly not very useful with the C++ standard library and its algorithms, and that is intentional. In particular, stateful predicates can only be useful if:


_DA>>The predicate is not copied: The standard algorithms make no such guarantee, and in fact assume that predicates are safely copyable.

S>Чем в конкретном случае копирование может помещать ?
Смысл этого замечания в следующем. Посмотрим на одну из популярных реализаций remove_if
template<class _FI, class _Pr> inline
    _FI remove_if(_FI _F, _FI _L, _Pr _P)
    {_F = find_if(_F, _L, _P);
    if (_F == _L)
        return (_F);
    else
        {_FI _Fb = _F;
        return (remove_copy_if(++_F, _L, _Fb, _P)); }}

Чудесный код, неправда ли? Так вот, тут экземпляр предиката _P передается в два разных алгоритма. У Саттера с Александреску пример с нахождением третьего элемента. В их случае получится, что этот третий элемент будет найден и в find_if и в remove_copy_if (на самом деле это будет уже шестой элемент). В нашем же случае да, ничего страшного с этой реализацией. Но могло бы быть и по-другому?

_DA>>The predicate is applied in a documented deterministic order: The standard algorithms generally make no guarantee about the order in which the predicate will be applied to the elements in the range. In the absence of guarantees about the order in which objects will be visited, operations like "flag the third element" (see Examples) make little sense, because which element will be visited "third" is not well-defined.

S>Задумался, вроде как в нашем конкретном случае должно все работать в порядке обхода итераторов, но в стандарте пока ничего не нашел.
S>Честно гря, как-то даже не задумывался, что последовательность применения предиката может оттличаться от последовательности итерирования.

S>Буду искать, если есть куда в стандарте, то ткните пальцем плз.

Ну так в том то и дело, что нет никаких гарантий порядка обхода в стандарте.

_DA>>Этот код непереносим. В некоторых версиях STL он работать не будет. И есть подозрение, что во многих версиях.

S>У меня как раз обратное подозрение, что на многих = он будет работать.

Да, тут я, пожалуй, погорячился.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[6]: Как удалить каждый третий элемент
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 09:45
Оценка:
Здравствуйте, HiSH, Вы писали:

HSH>Здравствуйте, HiSH, Вы писали:


HSH>>Уже прямо боюсь что-то говорить Поэтому просто спрошу — а разве не рекомендуется делать функторы stateless, т. к. в алгоритмах они могут копироватьсся? Этот пример работет, т. к. функтор, с которого была снята копия больше не используется — такое поведение где-то (в Стандарте) оговаривается?

HSH>>ЗЫ. Если i сделать статическим членом, тоже, ИМХО, не поможет — нет гарантии, что функтор не будет применен к какому-то объекту дважды.

HSH>Совсем забыл — или использовать передачу функтора по ссылке:

HSH>
HSH>    v.erase (
HSH>            remove_if<vector<int>::iterator, vector<int>::iterator, Func&>( v.begin(), v.end(), Func() ), 
HSH>            v.end( ) 
HSH>        );
HSH>



Не факт, что он внутри не скопируется. Стандартные алгоритмы часто внутри вызывают хелпер функции (ну по крайней мере у меня). Т.ч. это неправильно.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Как удалить каждый третий элемент
От: Кодт Россия  
Дата: 15.03.06 11:34
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Этот код непереносим. В некоторых версиях STL он работать не будет. И есть подозрение, что во многих версиях.


Для того, чтобы сделать его переносимым — достаточно вынести состояние за пределы экземпляра функтора.
struct State
{
  .....
};

struct Functor
{
  State* state;
  explicit Functor(State* st) : state(st) {}
  some operator()(some args) const // stateless, поэтому и const
  {
    ..... state->change() .....
  }
};

......
State state(init);
x = std::play_with_functor(Functor(&state));
y = state.result();

Для тех, кто не любит создавать лишние переменные,
x = std::play_with_functor(Functor(std::auto_ptr(new State(init)).get()));

или объявить нужные члены State как mutable и
x = std::play_with_functor(Functor(&State(init)));
Перекуём баги на фичи!
Re[6]: Как удалить каждый третий элемент
От: Кодт Россия  
Дата: 15.03.06 11:36
Оценка:
Здравствуйте, HiSH, Вы писали:

HSH>Совсем забыл — или использовать передачу функтора по ссылке:

HSH>    v.erase (
HSH>            remove_if<vector<int>::iterator, vector<int>::iterator, Func&>( v.begin(), v.end(), Func() ), 
HSH>            v.end( ) 
HSH>        );

Ошибка! Func() — это rvalue, оно приводится к const lvalue. Впрочем, VC относится к этому пофигистично.
Перекуём баги на фичи!
Re[6]: Как удалить каждый третий элемент
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 11:40
Оценка: +2
Здравствуйте, Кодт, Вы писали:

К>Для того, чтобы сделать его переносимым — достаточно вынести состояние за пределы экземпляра функтора.


А как быть с порядком применения функтора к элементам последовательности?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Как удалить каждый третий элемент
От: Кодт Россия  
Дата: 15.03.06 13:52
Оценка:
Здравствуйте, remark, Вы писали:

К>>Для того, чтобы сделать его переносимым — достаточно вынести состояние за пределы экземпляра функтора.


R>А как быть с порядком применения функтора к элементам последовательности?


Для некоторых алгоритмов порядок определён.
Хотя в данном случае, проще написать цикл, чем крутиться с собственными функторами или итераторами.
int n=v.size();
int w=0; // w - write
for(int r=0; r!=n; ++r) // r - read
{
  if(r%3!=0)
    if(w!=r) v[w++] = v[r];
}
v.resize(w);
Перекуём баги на фичи!
Re[8]: Как удалить каждый третий элемент
От: remark Россия http://www.1024cores.net/
Дата: 15.03.06 13:55
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, remark, Вы писали:


К>>>Для того, чтобы сделать его переносимым — достаточно вынести состояние за пределы экземпляра функтора.


R>>А как быть с порядком применения функтора к элементам последовательности?


К>Для некоторых алгоритмов порядок определён.

К>Хотя в данном случае, проще написать цикл, чем крутиться с собственными функторами или итераторами.
К>
К>int n=v.size();
К>int w=0; // w - write
К>for(int r=0; r!=n; ++r) // r - read
К>{
К>  if(r%3!=0)
К>    if(w!=r) v[w++] = v[r];
К>}
К>v.resize(w);
К>



Да вообще — std::for_each — suxx! Надо юзать BOOST_FOREACH. Или ждать поддержки foreach в языке.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.