Фильтр с помощью STL

278
12 марта 2017, 07:17

Что-то ощущение, что вопрос из серии "как я сам недотумкал", но...

Есть генератор (чисел, но лучше объектов). В идеале - как-то возвращает, что закончил генерировать (хорошо бы, чтоб можно было и istream_iterator передать, и лямбду, скажем...), но - скрепя сердце - согласен даже на просто количество. Дальше - есть предикат, который в сам генератор не зашивается (а если зашивается - то мы точно не можем сказать заранее, сколько значений будет сгенерировано!)

Их хочется отфильтровать и отправить куда-то.

Частями делается просто - скажем, generate_n в какой-то вектор (через back_inserter), потом - copy_if с предикатом - скажем, в ostream_iterator.

Написать собственный код еще проще :)

Но хочется извратиться - через STL и без дополнительного хранения в контейнере. В идеале - одной строкой (один вложенный вызов).

Ощущение, что крутится что-то такое рядом, но что-то никак не дается...

Вот пример кода:

vector<int> v(1000);
generate(v.begin(),v.end(),[](){.....});
copy_if(v.begin(),v.end(),[](){.....},
        ostrim_iterator<int>(cout,"\n"));

Как сделать это же БЕЗ дополнительного вектора? Если количество генерируемых объектов может быть очень велико?

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

Свой код выглядит примерно так:

int n;
ostrim_iterator<int> os(cout,"\n");
while([&n](){ return true; /* false по окончании генерации*/ })
{
     if (pred(n)) *os++ = n;
}

Т.е. пока генерируется, просто проверяем предикатом и отправляем через итератор.

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

Генератор -> Фильтр -> Выход

не должна быть редкостью, так что стандартная библиотека должна бы содержать ее решение?

Update
Придумался вариант - написание итератора от генератора. Т.е. с каждым ++ этот итератор возвращает вновь сгенерированное значение. Тогда хватит вообще обычного copy_if. Нет такого стандартного адаптера, превращающего генератор в итератор?...

Answer 1

возможно стоит поиграться с rangeV3 эрика нилберта, все-таки это когда то станет стандартом: https://ericniebler.github.io/range-v3/ код нет возможности проверить, но думаю копать примерно так:

//взято из тестов
auto ns = view::generate([]() mutable {
        static int N;
        return ++N;
});
auto rng = ns | view::take_while([](int i) { return i < 5; }); //сюда нужно вставить ваш предикат
//ну и отправляем rng в std::cout:
ranges::for_each(myRanges, [](auto const& r) { std::cout << r << '\n'; });
//либо вроде даже так, не помню точно:
std::cout<<rng;

если нужны примеры, то есть в тестах у него: https://github.com/ericniebler/range-v3/tree/master/test

READ ALSO
Как получить значение из output?

Как получить значение из output?

Как получить значение из тега Output?Это ползунокКак можно реализовать получение значения

348
Проверка на уникальность email с помощью Js

Проверка на уникальность email с помощью Js

Есть форма регистрации и в ней ипнут, который на вход принимает email пользователя:

298
Проблема с mouseup на странице

Проблема с mouseup на странице

Есть элемент span на форме, в onmousedown которого производится его удаление и вызов некоего событияВ этом событии отправляется Ajax-запрос к серверу

264
динамическая подгрузка модуля webpack 2 +

динамическая подгрузка модуля webpack 2 +

Не получается динамически подгружать модульДелаю по документации раздел: require

412