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

Лямбда выражения - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 30, средняя оценка - 4.90
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 14:33     Лямбда выражения #1
Здрасьте)
вопрос по новому стандарту, в который ввели лямбда-выражения.
создаю класс, у которого есть поле data, типа map.
C++
1
map <string, list<string> > data;
заполняю его. и теперь мне нужно отсортировать списки, которые в нём находятся.
первый логичный вариант -
C++
1
2
for(map <string, list<string> > :: iterator p = data.begin(); p != data.end(); ++p)
                    p->second.sort();
(кстати, в этом случае - всё прекрасно работает)
но задание у меня такого, что нельзя использовать циклы, тогда пробую так:
C++
1
2
3
4
for_each(data.begin(), data.end(), [](pair<string, list<string> > p)
                 {
                     p.second.sort();
                 });
но при вызове
C++
1
2
3
4
5
6
7
8
9
10
11
map<string, list<string> > :: iterator p = data.begin();
for_each(&mas[0], &mas[size],[&p, &result](int x)
        {
            if (x == 1)
            {
                list<string> help;
                set_intersection(result.begin(), result.end(), p->second.begin(), p->second.end(), back_inserter(help));                
                result.assign(help.begin(), help.end());
                ++p;
            }
}
обнаруживается, что списки в мэпе не отсортированы!
возвращиюсь к сорту (с помощью лямбды) вывожу значения всего мепа (по спискам) и дейстительно! лямбда-выражение его не отсортировало.
Появилась идея, что нужно включить data в список захвата, но строчка
C++
1
2
3
4
for_each(data.begin(), data.end(), [&data](pair<string, list<string> > p)
                 {
                     p.second.sort();
                 });
не компилируется, ибо data - член класса, который "не является переменной".

Если нужен полный код - вот он.
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Var 9.cpp: определяет точку входа для консольного приложения.
//Имеется список 40 студентов, изучающих математику, физику, биологию и химию, заданный в файле в виде строк 
//Фамилия    предмет
 
//Каждый предмет изучает около 20 студентов. Разработать структуры данных, позволяющих эффективно отвечать на запросы вида 
//«Выдать всех студентов, изучающих биологию и химию, но не изучающих физику».
 
#include "stdafx.h"
#include <algorithm>
#include <iostream>
#include <string>
#include <fstream>
#include <list>
#include <map>
#include <iterator>
using namespace std;
 
/*
биологию   mas[0]
математику mas[1]
физику     mas[2]
химию      mas[3]
*/
 
class stud_file
{
map <string, list<string> > data;
list<string> all_stud;
 
public:
    
    stud_file (string s) 
    {
        ifstream FS; //Fs(s) ?
        FS.open(s);
                 string Fam, pred;
                 while(!FS.eof()) //а как читать?
                 {
                    FS >> Fam;
                    FS >> pred;
                    data[pred].push_back(Fam);
 
                    list<string> :: iterator pb = all_stud.begin();
                    list<string> :: iterator pe = all_stud.end();
                    if (find(pb, pe, Fam) == pe)
                    {
                        all_stud.push_back(Fam);
                    }
 
                 }
                 FS.close();
 
                 all_stud.sort(); //надо сортировать
                 
                 for_each(data.begin(), data.end(), [&data](pair<string, list<string> > p)
                 {
                     p.second.sort();
                 });
 
 
 
                 for(auto it = data.begin(); it!= data.end(); ++it)
                 {
                     for(auto itl = it->second.begin(); itl != it->second.end(); ++itl)
                     {
                         cout<<' '<<*itl<<' ';
                     }
                     cout<<"987"<<'\n';
                 }
            
 
 
 
                /* for(map <string, list<string> > :: iterator p = data.begin(); p != data.end(); ++p)
                    p->second.sort();*/
     }
 
    void print (int mas[], int size) //ваще беда))
    {
        list<string> result;
        result.assign(all_stud.begin(), all_stud.end());
        map<string, list<string> > :: iterator p = data.begin();
 
        for_each(&mas[0], &mas[size],[&p, &result](int x)
        {
            if (x == 1)
            {
                list<string> help;
                set_intersection(result.begin(), result.end(), p->second.begin(), p->second.end(), back_inserter(help));                
                result.assign(help.begin(), help.end());
                ++p;
            }
            else
                if (x == -1)
                {
                    string help[40];
                    auto it = set_difference(result.begin(), result.end(), p->second.begin(), p->second.end(), help);
                    result.assign(help, it);
                    ++p;
                }
                else
                    ++p;
        });
        /*for(int i = 0; i<size; ++i)
        {
            if (mas[i] == 1)
            {
                string help[40];
                auto it = set_intersection(result.begin(), result.end(), p->second.begin(), p->second.end(), help);
                result.assign(help, it);
                ++p;
            }
            else
                if (mas[i] == -1)
                {
                    string help[40];
                    auto it = set_difference(result.begin(), result.end(), p->second.begin(), p->second.end(), help);
                    result.assign(help, it);
                    ++p;
                }
        }*/
        for(list<string> :: iterator l = result.begin(); l != result.end(); ++l)
            cout<< *l<<'\n';
        cout<<"\n";
    }
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(0, "Rus");
    const int n = 4;
    int mas[n] = {0,0,0,0};
 
    stud_file Stud("file.txt");
 
    cout<<"†††††††††††††††††††††††††††††††††††††††††††††\n";
    cout<<"Установите нужные параметры поиска\n";
    int con = 0;
    while (con !=-1)
    {
        cout<<"†††††††††††††††††††††††††††††††††††††††††††††\n";
        cout<<"биология       => 0\n";
        cout<<"математика     => 1\n";
        cout<<"физика         => 2\n";
        cout<<"химия          => 3\n";
        cout<<"текущий выбор  => 101\n";
        cout<<"вывести список => 102\n";
        cout<<"Выйти          => -1\n";
        cin >> con;
 
        switch (con)
        {
        case 0:
        case 1:
        case 2:
        case 3:
            {
                cout<<"изучает   =>1\n";
                cout<<"неважно   =>0\n";
                cout<<"неизучает =>-1\n";
                int i;
                cin>>i;
                mas[con] = i;
                break;
            }
        case 101:
            {
                for_each(&mas[0], &mas[n], [](int x){cout<<x<<' ';});
                cout<<"\n";
                break;
            }
        case 102:
            {
                Stud.print(mas,n);
            }
        }
    }
    return 0;
}
хочу разобраться именно с лямбда выражениями. Напомню - циклы использовать нельзя, а объект-функции просто не хочется
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.11.2011, 14:33     Лямбда выражения
Посмотрите здесь:

C++ лямбда заполнения вектора
Передача лямбда в функции C++
C++ лямбда функция
С++11 Лямбда-выражения и вывод результата C++
C++ Какова польза лямбда выражений
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:16     Лямбда выражения #21
Цитата Сообщение от ForEveR Посмотреть сообщение
diagon, Значит я не прав.
Хех...
Нет, gcc хитрее.
Он оба варианта не компилирует >_<
До этого с вектором int'ов тестировал, все работало.
Пруф.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:20     Лямбда выражения #22
diagon, Да... Мапа вроде создается как map<const Key, Value>...
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 15:21     Лямбда выражения #23
diagon, что-то мне расхотелось обновляться до нового MinGW gcc 4.5.1 mingw компилирует for_each для std::list<int> с перезаписью каждого элемента ( [&counter]( int &e ){ e = counter++; } )
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:21     Лямбда выражения #24
Код
   *  Meets the requirements of a <a href="tables.html#65">container</a>, a
   *  <a href="tables.html#66">reversible container</a>, and an
   *  <a href="tables.html#69">associative container</a> (using unique keys).
   *  For a @c map<Key,T> the key_type is Key, the mapped_type is T, and the
   *  value_type is std::pair<const Key,T>.
Из сорцов.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 15:22     Лямбда выражения #25
ForEveR, точно. не подумал. прошу прощения, предыдущее сообщение бессмысленно.
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:24     Лямбда выражения #26
Цитата Сообщение от ForEveR Посмотреть сообщение
Из сорцов.
Но если изменить string на const string, то ничего не изменится...
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 15:26  [ТС]     Лямбда выражения #27
вообщем vs на всё ругается, и на &p, и на transform, ибо
C++
1
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(260): error C2678: бинарный "=": не найден оператор, принимающий левый операнд типа "const std::string" (или приемлемое преобразование отсутствует)
щас уже нет время - нужно бежать, а вечером ещё вернусь к этому...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:37     Лямбда выражения #28
diagon, Где изменить? Разыменованный итератор для мапы возвращает value_type то есть pair<const Key, Value>.

Добавлено через 4 минуты
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 <string>
#include <map>
#include <list>
#include <algorithm>
#include <iterator>
 
int main()
{
   std::list<std::string> lst = {"hello", "and", "what"};
   std::map<std::string, std::list<std::string>> data = {make_pair("hello", lst)};
   std::for_each(data.begin(), data.end(), [&data]
   (std::map<std::string, std::list<std::string>>::value_type value)
   {
      data.erase(value.first);
      value.second.sort();
      data.insert(value);
   });
   std::for_each(data.begin(), data.end(),
   [](const std::map<std::string, std::list<std::string>>::value_type& value)
   {
      std::cout << "Key: " << value.first << std::endl;
      std::cout << "Values: " << std::endl;
      std::copy(value.second.begin(), value.second.end(),
      std::ostream_iterator<std::string>(std::cout, "\n"));
   });
}
Как вариант.

Добавлено через 37 секунд
http://liveworkspace.org/code/380380...8af593973a0871
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:37     Лямбда выражения #29
Цитата Сообщение от ForEveR Посмотреть сообщение
diagon, Где изменить? Разыменованный итератор для мапы возвращает value_type то есть pair<const Key, Value>.
Везде
http://liveworkspace.org/code/d40aa7...00e199f9522f71
И вообще, я думал, что если не указывать тип возвращаемого значения, то компилятор сам его подберет.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:41     Лямбда выражения #30
diagon, Алгоритм transform делает ничто иное как:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  template<typename _InputIterator, typename _OutputIterator,
       typename _UnaryOperation>
    _OutputIterator
    transform(_InputIterator __first, _InputIterator __last,
          _OutputIterator __result, _UnaryOperation __unary_op)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator,
            // "the type returned by a _UnaryOperation"
            __typeof__(__unary_op(*__first))>)
      __glibcxx_requires_valid_range(__first, __last);
 
      for (; __first != __last; ++__first, ++__result)
    *__result = __unary_op(*__first);
      return __result;
    }
Где в данном случае __result - итератор мапы. И возвращаемое значение оператора * у итератора мапы является map::value_type, где map::value_type == pair<const Key, Value>.
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:43     Лямбда выражения #31
Цитата Сообщение от ForEveR Посмотреть сообщение
Где в данном случае __result - итератор мапы. И возвращаемое значение оператора * у итератора мапы является map::value_type, где map::value_type == pair<const Key, Value>.
Ну так там ключ константа.
C++
1
[] ( std::pair< const std::string, std::list<std::string>> elem) -> std::pair< const std::string, std::list<std::string> >
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.11.2011, 15:50     Лямбда выражения
Еще ссылки по теме:

Почему не работают лямбда-выражения? C++
C++ Изменение содержимого вектора из лямбда функции
C++ Рекурсивная лямбда

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:50     Лямбда выражения #32
diagon, Да. Ключ константа. В типе самой мапы. Поэтому такой код работать не будет. Только через методы.

Если конкретнее. __result - итератор мапы. Его разыменовывают и получают std:air<const Key, Value> затем пытаются присвоить результат выполнения функтора. Что понятное дело невозможно.
Yandex
Объявления
10.11.2011, 15:50     Лямбда выражения
Ответ Создать тему
Опции темы

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