On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 17.05.18 17:50. Заголовок: Как подсчитать количество заданных элементов в контейнере?


Иногда возникает задача подсчета заданных элементов в контейнере.

Например, пусть имеется массив целых чисел

 
int a[] = { 1, 2, 3, 1, 2, 2 };


и требуется подсчитать, сколько раз в этом массиве присутствуют значения 1 и 2.

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

На ум помимо обычных циклов сразу же приходит стандартный алгоритм std::count или std::count_if.

Один из подходов может выглядеть следующим образом

 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <initializer_list>

template <typename R, typename T>
auto matches( const R &range, std::initializer_list<T> lst )
{
return std::count_if( std::begin( range ), std::end( range ),
[&]( auto x )
{
return std::binary_search( std::begin( lst ), std::end( lst ), x );
} );
}

int main()
{
int a[] = { 1, 2, 3, 1, 2, 2 };

std::cout << matches( a, { 1, 2 } ) << std::endl;
}


Вывод программы на консоль
 
5


В этой реализации функции помимо стандартного алгоритма std::count_if используется алгоритм std::binary_search. Чтобы его можно было использовать в данном контексте, заданные значения должны быть отсортированы, чтобы образовать отсортированный список инициализации.

Другой подход - это использовать так называемые "сворачиваемые выражения" (fold expressions), введенные в стандарте C++ 17.

Вот как будет выглядеть соответствующая реализация функции.

 
#include <iostream>
#include <algorithm>
#include <iterator>

template <typename R, typename ...Ts>
auto matches( const R &range, Ts... ts )
{
return ( std::count( std::begin( range ), std::end( range ), ts ) + ... + 0 );
}

int main()
{
int a[] = { 1, 2, 3, 1, 2, 2 };

std::cout << matches( a, 1, 2 ) << std::endl;
}


Здесь уже не важно отсортированы ли заданные значения или нет, так как алгоритм std::count вызывается отдельно для каждого заданного значения.

Если у вас есть свои идеи, как выполнить эту задачу, то можете разместить сообщения к теме со своими предложениями.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 1 [только новые]





ссылка на сообщение  Отправлено: 18.05.18 15:06. Заголовок: Похожая задача возни..


Похожая задача возникает, когда надо добавить в вектор несколько элементов.

До введения стандарта C++ 17 это можно было сделать с использованием метода insert и списка инициализации. Ниже приведена демонстрационная программа

 
#include <iostream>
#include <vector>

int main()
{
std::vector<int> v( { 1, 2, 3 } );

v.insert( v.end(), { 4, 5, 6 } );

for ( const auto &item : v ) std::cout << item << ' ';
std::cout << std::endl;
}


Вывод программы на консоль

 
1 2 3 4 5 6


С появлением стандарта C++ 17 можно написать обобщенную функцию следующего вида, как показано в последующей демонстрационной программе.

 
#include <iostream>
#include <vector>

template <typename T, typename ...Ts>
void insert_all( std::vector<T> &v, Ts... ts )
{
v.reserve( v.size() + sizeof...( ts ) );
( v.push_back( ts ), ... );
}

int main()
{
std::vector<int> v( { 1, 2, 3 } );

insert_all( v, 4, 5, 6 );

for ( const auto &item : v ) std::cout << item << ' ';
std::cout << std::endl;
}


Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 5
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет