Ищу алгоритм STL
От: Stepkh  
Дата: 27.09.04 07:06
Оценка:
Привет всем !

Есть струтура

 struct st
{
 int a,b,c;
}


есть старый добрый вектор

 vector <int> v1;
 vector <st> v2;


Хочу скопировать элемены v2 в v1 (есстесвенно мы понимаем, что копируем только какое-то поле из вышеуказнной структуры)
Начинам искать среди алгоритмов и натыкамся на вот такую прелесть:

transform (v2.begin(), v2.end(), back_inserter(v1), foo());

, где foo() извлекает нужное поле из структуры st.

Все хорошо, но мне не протсо хочется скопировать , мне надо скопировать с условием:

   copy_if (v2.begin(), v2.end(), v1.begin(), (my  condition))

Но тут требуются одинаковые типы источника и получателя.
В связи с этим вопрос: как объединить transform и copy_if? Или есть еще какой-нибудь вариант?
Re: Ищу алгоритм STL
От: Анатолий Широков СССР  
Дата: 27.09.04 07:45
Оценка:
S>В связи с этим вопрос: как объединить transform и copy_if? Или есть еще какой-нибудь вариант?

Решение видится в том, чтобы оставить copy_if и написать свой back_insert_iterator и хелпер к нему наподобие back_inserter (см. заголовочный файл iterator в качестве примера реализации), который принимает, помимо контейнера, функтор осуществляющий преобразование типов:

copy_if(v2.begin(), v2.end(), transform_back_inserter(v1, foo()), <условие>);
Re: Ищу алгоритм STL
От: a1ex_k Россия  
Дата: 27.09.04 07:48
Оценка: 6 (1)
Здравствуйте, Stepkh, Вы писали:

S>В связи с этим вопрос: как объединить transform и copy_if? Или есть еще какой-нибудь вариант?

красивым решением было бы использование transform_copy_if, но его в стандарте нет
впрочем как и copy_if, хотя штука полезная и в некоторых реализациях STL все же присутствует
поэтому предлагаю написать transform_copy_if и положить его в свою копилку,
но перед этим поискать его реализацию в сети
еще один вариант использовать boost
http://www.boost.org/libs/iterator/doc/filter_iterator.html
Re: Ищу алгоритм STL
От: Bell Россия  
Дата: 27.09.04 08:00
Оценка:
Здравствуйте, Stepkh, Вы писали:

Готового алгоритма для такого случая, увы, нет.
Вариатны:
1. std::transform, для результата связка remove_if + erase.
Плюсы — стандартые алгоритмы, ничего не надо писать дополнительно.
Минусы — требуется 2 прохода.

2.
Написать свой output_iterator, и использовать его в std::copy_if.
Плюсы — все делается за 1 проход, не требуется модификация структуры st.
Минусы — надо писать этот самый output_iterator.

3.
Определить в структуре st operator int(), и использовать std::copy_if (кстати утверждение о том, что для std::copy_if "требуются одинаковые типы источника и получателя" не является верным)
Плюсы — все делается за 1 проход
Минусы — требуется модификация структуры st, наличие оператора преобразования может повлечь за собой определенные проблемы.

4.
Написать явный цикл.
Любите книгу — источник знаний (с) М.Горький
Re: Ищу алгоритм STL
От: sadomovalex Россия http://sadomovalex.blogspot.com
Дата: 27.09.04 08:06
Оценка:
Здравствуйте, Stepkh, Вы писали:

S>Привет всем !


S>Есть струтура


S>
S> struct st
S>{
S> int a,b,c;
S>}
S>


S>есть старый добрый вектор


S>
S> vector <int> v1;
S> vector <st> v2;
S>


S>Хочу скопировать элемены v2 в v1 (есстесвенно мы понимаем, что копируем только какое-то поле из вышеуказнной структуры)

S>Начинам искать среди алгоритмов и натыкамся на вот такую прелесть:

S>
S>transform (v2.begin(), v2.end(), back_inserter(v1), foo());
S>

S>, где foo() извлекает нужное поле из структуры st.

S>Все хорошо, но мне не протсо хочется скопировать , мне надо скопировать с условием:


S>
S>   copy_if (v2.begin(), v2.end(), v1.begin(), (my  condition))
S>

S>Но тут требуются одинаковые типы источника и получателя.
S>В связи с этим вопрос: как объединить transform и copy_if? Или есть еще какой-нибудь вариант?

Использовать boost::lambda. К примеру следующий пример показывает, как скопировать поле st::a, если выполняется какое-нибудь условие:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>

...

bool some_condition(const st &s)
{
    return ((s.a + s.b + s.c) > 0);
}

...

for_each(v2.begin(), v2.end(), if_then(bind(&some_condition, _1),
    bind(&vector<int>::push_back, &v1, bind(&st::a, _1))));
"Что не завершено, не сделано вовсе" Гаусс
Re[2]: Ищу алгоритм STL
От: Stepkh  
Дата: 27.09.04 08:26
Оценка:
Здравствуйте, Bell, Вы писали:

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


B>Готового алгоритма для такого случая, увы, нет.

B>Вариатны:
B>1. std::transform, для результата связка remove_if + erase.
B>Плюсы — стандартые алгоритмы, ничего не надо писать дополнительно.
B>Минусы — требуется 2 прохода.

Негодится. Нужен именно один проход

B>2.

B>Написать свой output_iterator, и использовать его в std::copy_if.
B>Плюсы — все делается за 1 проход, не требуется модификация структуры st.
B>Минусы — надо писать этот самый output_iterator.

Терпимый минус ... Хотя хотелось бы чтобы все было в одном флаконе

B>3.

B>Определить в структуре st operator int(), и использовать std::copy_if (кстати утверждение о том, что для std::copy_if "требуются одинаковые типы источника и получателя" не является верным)

Согласен

B>Плюсы — все делается за 1 проход

B>Минусы — требуется модификация структуры st, наличие оператора преобразования может повлечь за собой определенные проблемы.

Самый легкий путь. Бо требует минимальных изменений.

B>4.

B>Написать явный цикл.

Ой, вот этого не надо — некрасиво будет

Итак по ранжиру:
2 — достигаем универсализма
3 — решаем поставленную задачу локально на сейчас. Быстро дешево и сердито, но...
1 — хорошо, но 2 прохода просто убивают
4 — все хорошо окромя эстетики
Re: Ищу алгоритм STL
От: Stepkh  
Дата: 27.09.04 08:27
Оценка:
Здравствуйте, Stepkh, Вы писали:

S>Привет всем !


Спасибо всем ответимшим!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.