Форум программистов, компьютерный форум CyberForum.ru

unordered_multimap - интервальный конструктор - C++

Восстановить пароль Регистрация
 
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.07.2013, 10:14     unordered_multimap - интервальный конструктор #1
Как можно воспользоваться интервальным конструктором для unordered_multimap в таком вот коде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <iterator>
 
using input = std::istream_iterator<std::string>;
 
int main(int argc, char** argv) 
{
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
   std::unordered_multimap<std::string, size_t> words{input(iss), input()};
 
   return 0;
}
Контейнер должен хранить слова и количество букв в слове.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.07.2013, 10:14     unordered_multimap - интервальный конструктор
Посмотрите здесь:

Конструктор C++
Интервальный таймер C++
Конструктор C++
Интервальный тип C++
C++ конструктор
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
04.07.2013, 11:44     unordered_multimap - интервальный конструктор #2
Цитата Сообщение от DiffEreD Посмотреть сообщение
Контейнер должен хранить слова и количество букв в слове.
Поэтому и итератор должен возвращать pair, а не string.
Т.е. как минимум не хватает преобразования:
C++
1
2
3
4
std::pair<std::string, size_t> make_element( const std::string& s )
{
    return std::make_pair( s, s.length() );
}
И, по-моему, скобки должны быть круглые, а не фигурные (иначе это список инициализации).

Дальше, чтобы итератор возвращал пару, вероятно надо мутить свой класс итератора. Ну или можно делать вставку поэлементно, типа так:
C++
1
words.insert( make_element( *input(iss) ));
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.07.2013, 12:12  [ТС]     unordered_multimap - интервальный конструктор #3
Ну и как можно сделать что бы istream_iterator возвращал pair?
Tulosba
:)
Эксперт C++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
04.07.2013, 12:13     unordered_multimap - интервальный конструктор #4
Цитата Сообщение от DiffEreD Посмотреть сообщение
Ну и как можно сделать что бы istream_iterator возвращал pair?
Цитата Сообщение от Tulosba Посмотреть сообщение
вероятно надо мутить свой класс итератора.
собственно вот
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
04.07.2013, 12:43     unordered_multimap - интервальный конструктор #5
Так должно работать (не проверял)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <iterator>
 
std::istream& operator >> (std::istream& is, std::pair<std::string, int> &p)
{
    is >> p.first;
    p.second = p.first.size();
    return is;
}
 
using input = std::istream_iterator<std::pair<std::string, int>>;
 
int main()
{
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
   std::unordered_multimap<std::string, std::size_t> words(input(iss), input());
   return 0;
}
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.07.2013, 12:53  [ТС]     unordered_multimap - интервальный конструктор #6
В принципе, работать будет если в std закинуть, но это плохой стиль программирования:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <unordered_map>
#include <iterator>
 
namespace std
{
   std::istream& operator >> (std::istream& is, std::pair<std::string, int> &p)
   {
     is >> p.first;
     p.second = p.first.size();
     return is;
   }
}
 
using input = std::istream_iterator<std::pair<std::string, int>>;
 
int main(int argc, char** argv) 
{
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
   std::unordered_multimap<std::string, size_t> words {input(iss), input()};
   for (auto& i : words) std::cout<<std::setw(20)<<std::left<<i.first<<" : "<<i.second<<'\n';
 
   return 0;
}
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
04.07.2013, 13:27     unordered_multimap - интервальный конструктор #7
Цитата Сообщение от DiffEreD Посмотреть сообщение
В принципе, работать будет если в std закинуть, но это плохой стиль программирования:
Почему перегрузить operator >> для своего типа является плохим стилем?
Или Вы имели в виду, что подключать свою функцию к другому пространству имен - плохой стиль? Тогда я согласен.

Вот вариант с помощью итераторов. Знаю, криво написано, но работает
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <unordered_map>
#include <iterator>
 
template <typename T, typename U, typename Func>
class istream_iterator_pair: public std::iterator<std::input_iterator_tag, T>
{
    std::istream_iterator<T> data;
    U prop;
    Func func;
public:
    istream_iterator_pair( std::istream_iterator<T> data_in, Func f ):
        data( data_in ), func( f )
    {
        prop = func(*data);
    }
 
    istream_iterator_pair(const istream_iterator_pair &x):
        istream_iterator_pair(x.data, x.func) {}
 
    istream_iterator_pair operator ++ ()
    {
        ++data;
        prop = func(*data);
        return *this;
    }
 
    istream_iterator_pair operator ++ (int)
    {
        istream_iterator_pair temp(*this);
        ++*this;
        return temp;
    }
 
    std::pair<std::string, size_t> operator * () { return {*data, prop}; }
 
    bool operator != (const istream_iterator_pair &x)
    {
        return data != x.data;
    }
};
 
int main(int argc, char** argv)
{
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
 
   auto func = [](const std::string &str){return str.size();};
   using input = std::istream_iterator<std::string>;
   using pair_in = istream_iterator_pair<std::string, size_t, decltype(func)>;
 
   std::unordered_multimap<std::string, size_t> words ( pair_in( input(iss), func ),
                                                    pair_in( input(), func ) );
   for (auto& i : words) std::cout<<std::setw(20)<<std::left<<i.first<<" : "<<i.second<<'\n';
 
   return 0;
}
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.07.2013, 13:39  [ТС]     unordered_multimap - интервальный конструктор #8
Цитата Сообщение от Olivеr Посмотреть сообщение
Почему перегрузить operator >> для своего типа является плохим стилем?
Я про закидывание его в std, это имелось ввиду.

Добавлено через 4 минуты
Цитата Сообщение от Olivеr Посмотреть сообщение
Вот вариант с помощью итераторов
Вот за это спасибо.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
04.07.2013, 14:19     unordered_multimap - интервальный конструктор #9
Кое что переделал. Думаю так будет лучше:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
template <typename value_type, typename property_type>
class istream_iterator_pair: public std::iterator<std::input_iterator_tag, value_type>
{
    using input_value_iter = std::istream_iterator<value_type>;
    using Func = std::function<property_type(const value_type&)>;
 
    input_value_iter value;
    property_type property;
    Func func;
 
    void updateProperty()
    {
        property = (func != nullptr) ? func(*value) : property_type();
    }
 
public:
 
    istream_iterator_pair():
        value( input_value_iter() ), property(), func(nullptr) {}
 
    istream_iterator_pair(input_value_iter it, Func f):
        value(it), property(), func(f) { updateProperty(); }
 
    istream_iterator_pair(const istream_iterator_pair &x):
        istream_iterator_pair(x.value, x.func) {}
 
    istream_iterator_pair& operator ++ ()
    {
        ++value;
        updateProperty();
        return *this;
    }
 
    istream_iterator_pair operator ++ (int)
    {
        istream_iterator_pair temp(*this);
        ++*this;
        return temp;
    }
 
    bool operator != (const istream_iterator_pair &x)
    {
        return value != x.value;
    }
 
    std::pair<value_type, property_type>
    operator * () { return {*value, property}; }
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(int argc, char** argv)
{
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
 
   auto func = [](const std::string &str){return str.size();};
   using input = std::istream_iterator<std::string>;
   using pair_in = istream_iterator_pair<std::string, size_t>;
 
   std::unordered_multimap<std::string, size_t> words ( pair_in( input(iss), func ),
                                                    pair_in() );
   for (auto& i : words) std::cout<<std::setw(20)<<std::left<<i.first<<" : "<<i.second<<'\n';
 
   return 0;
}
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
04.07.2013, 14:43     unordered_multimap - интервальный конструктор #10
DiffEreD, boost::transform_iterator должен подойти.
Olivеr
 Аватар для Olivеr
411 / 407 / 13
Регистрация: 06.10.2011
Сообщений: 830
04.07.2013, 14:58     unordered_multimap - интервальный конструктор #11
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от gray_fox Посмотреть сообщение
DiffEreD, boost::transform_iterator должен подойти.
И вправду можно так:
C++
1
2
3
   std::unordered_multimap<std::string, size_t> words;
   std::transform( input(iss), input(), std::inserter(words, words.begin()),
                [](const std::string &str){ return std::make_pair(str, str.size()); } );
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
04.07.2013, 15:03     unordered_multimap - интервальный конструктор #12
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Olivеr, я что-то вроде этого имел ввиду
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_map>
 
#include <boost/iterator/transform_iterator.hpp>
 
 
int main() {
   using map_type    = std::unordered_multimap<std::string, std::size_t>;
   using pair_type   = map_type::value_type;
 
   struct transform {
 
      pair_type operator ()(std::string const& string) const noexcept {
         return std::make_pair(string, string.length());
      }
   };
 
   using istream_iterator     = std::istream_iterator<std::string>;
   using transform_iterator   = boost::transform_iterator<transform, istream_iterator, pair_type>;
 
   map_type map(transform_iterator{istream_iterator{std::cin}}, transform_iterator{});
   for (auto const& pair : map) {
      std::cout << pair.second << '\t' << pair.first << std::endl;
   }
}
правда как туда лябду запихнуть, не знаю)
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.07.2013, 15:27     unordered_multimap - интервальный конструктор #13
gray_fox, Как-то так.
C++
1
2
3
4
5
6
   auto transform = [](const std::string& string) { return std::make_pair(string, string.length()); };
 
   using istream_iterator     = std::istream_iterator<std::string>;
   using transform_iterator   = boost::transform_iterator<decltype(transform), istream_iterator, pair_type>;
 
   map_type map(transform_iterator{istream_iterator{std::cin}, transform}, transform_iterator{{}, transform});
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.07.2013, 16:12     unordered_multimap - интервальный конструктор
Еще ссылки по теме:

Конструктор C++
C++ Конструктор
C++ Конструктор

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
04.07.2013, 16:12     unordered_multimap - интервальный конструктор #14
Цитата Сообщение от Olivеr Посмотреть сообщение
И вправду можно так:
Так то конечно вариант с std::transform - самый адекватный)

Добавлено через 45 минут

Не по теме:

C boost::range ещё вариант, но я лично использовать такое не советую, уж больно перегружено выглядит)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
 
#define BOOST_RESULT_OF_USE_DECLTYPE
#include <boost/range/istream_range.hpp>
#include <boost/range/adaptor/transformed.hpp>
 
 
int main() {
   std::string text = "constructs the container with the contents of the range";
   std::istringstream iss(text);
 
   auto const map = boost::copy_range<std::unordered_multimap<std::string, std::size_t>>(
                       boost::istream_range<std::string>(iss)
                     | boost::adaptors::transformed([] (std::string const& string) {
                          return std::make_pair(string, string.length());
                     }));
 
   for (auto const& pair : map) {
      std::cout << pair.second << ' ' << pair.first << std::endl;
   }
}

Yandex
Объявления
04.07.2013, 16:12     unordered_multimap - интервальный конструктор
Ответ Создать тему
Опции темы

Текущее время: 14:16. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru