Форум программистов, компьютерный форум 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, 14:35     Лямбда выражения #2
Цитата Сообщение от IcyWind Посмотреть сообщение
[](pair<string, list<string> > p)
Передается по значению, т.е. создается новый объект.
Передавайте по ссылке
C++
1
pair<string, list<string> > &p
Еще лучше нормальный foreach использовать
C++
1
2
for ( auto &p : data )
  p.second.sort();
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:44     Лямбда выражения #3
А если так?

C++
1
2
3
4
[](pair<string, list<string> > &p)
                                 {
                                         p.second.sort();
                                 }
Добавлено через 22 секунды

Не по теме:

пока читал, опоздал :-)



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

Не по теме:

diagon, эх жаль, что мой gcc не понимает этот новый for. Красиво.

diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 14:47     Лямбда выражения #4
Цитата Сообщение от talis Посмотреть сообщение
diagon, эх жаль, что мой gcc не понимает этот новый for. Красиво.
А мой понимает
Bash
1
2
3
4
5
6
diagon@shadeware:~$ g++ --version
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая 
коммерческую ценность и применимость для каких-либо целей.
Только я компилирую с ключом -std=c++0x. Без него не работает.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 14:49     Лямбда выражения #5
diagon, я тоже с ключом. Просто я в основном под mingw сейчас сижу, давно не обновлял
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 14:53  [ТС]     Лямбда выражения #6
Цитата Сообщение от diagon Посмотреть сообщение
Передается по значению, т.е. создается новый объект, копирующий старый.
Передавайте по ссылке
C++
1
pair<string, list<string> > &p
нет, это строчка - аналог operator ()
for_each делает (*p)
список передаваемых параметров заключён в [], но я не передаю параметр
компилятор создаёт какую-то функцию, с каким-то именем, а то, что написано в () в моей записи - это аналог operator() для созданной компилятором объект-функции
и тогда запись
C++
1
pair<string, list<string> > &p
приведёт к ошибке компиляции - не соответствие типов
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 14:56     Лямбда выражения #7
Цитата Сообщение от IcyWind Посмотреть сообщение
нет, это эта строчка - аналог operator ()
Эта строчка - список аргументов.
Сравните сами
По значению - http://liveworkspace.org/code/c84dec...64f0eb121eaf0d
По ссылке - http://liveworkspace.org/code/a490b3...2567712fa79e1a
(Вывод внизу)
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 14:58     Лямбда выражения #8
IcyWind, Нет. Передавать параметр надо по ссылке. Конструкция [] (type param) ничто иное как передача параметров. Передавайте по ссылке и все будет ок.
IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 14:58  [ТС]     Лямбда выражения #9
Цитата Сообщение от ForEveR Посмотреть сообщение
IcyWind, Нет. Передавать параметр надо по ссылке. Конструкция [] (type param) ничто иное как передача параметров. Передавайте по ссылке и все будет ок.
C++
1
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(22): error C2664: void `anonymous-namespace'::<lambda0>::operator ()(std::pair<_Ty1,_Ty2> &) const: невозможно преобразовать параметр 1 из "std::pair<_Ty1,_Ty2>" в "std::pair<_Ty1,_Ty2> &"
ну и?
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 15:02     Лямбда выражения #10
IcyWind, в gcc всё ок. vs 10 тупит. а вообще выложите строчки, выдающие ошибку.
diagon
10.11.2011, 15:03
  #11

Не по теме:

Цитата Сообщение от IcyWind Посмотреть сообщение
C++
1
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(22): error C2664: void `anonymous-namespace'::<lambda0>::operator ()(std::pair<_Ty1,_Ty2> &) const: невозможно преобразовать параметр 1 из "std::pair<_Ty1,_Ty2>" в "std::pair<_Ty1,_Ty2> &"
ну и?
Студия такая студия...

IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 15:04  [ТС]     Лямбда выражения #12
ошибка тут
C++
1
2
3
4
5
6
7
8
template<class _InIt,
    class _Fn1> inline
    _Fn1 _For_each(_InIt _First, _InIt _Last, _Fn1 _Func)
    {   // perform function for each element
    for (; _First != _Last; ++_First)
        _Func(*_First);
    return (_Func);
    }
описание
C++
1
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(22): error C2664: void `anonymous-namespace'::<lambda0>::operator ()(std::pair<_Ty1,_Ty2> &) const: невозможно преобразовать параметр 1 из "std::pair<_Ty1,_Ty2>" в "std::pair<_Ty1,_Ty2> &"
silent_1991
10.11.2011, 15:04
  #13

Не по теме:

Цитата Сообщение от talis Посмотреть сообщение
мой gcc не понимает этот новый for
В чём проблема обновить?

ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:05     Лямбда выражения #14
IcyWind, Как ни странно for_each не предназначен для изменения контейнера. По лямбде можно. Если не получается - используйте алгоритмы который для этого предназначены. std::transform к примеру.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
10.11.2011, 15:06     Лямбда выражения #15
IcyWind, да не вырезку из стандартной библиотеки. Строчку, которая породила ошибку.

Не по теме:

silent_1991, нужна была причина. Теперь есть причина

IcyWind
8 / 8 / 2
Регистрация: 19.09.2011
Сообщений: 268
10.11.2011, 15:08  [ТС]     Лямбда выражения #16
C++
1
 for_each(data.begin(), data.end(), [](pair<string, list<string> > &p)
Добавлено через 1 минуту
Цитата Сообщение от ForEveR Посмотреть сообщение
IcyWind, Как ни странно for_each не предназначен для изменения контейнера. По лямбде можно. Если не получается - используйте алгоритмы который для этого предназначены. std::transform к примеру.
а да...наверно в этом всё дело
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:09     Лямбда выражения #17
Как предложили выше можно через transform.
C++
1
2
3
4
5
transform( data.begin(), data.end(), data.begin(), [] ( pair< string, list< string > > p)
{
   p.second.sort();
   return p;
} );
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:11     Лямбда выражения #18
IcyWind,
C++
1
std::transform(data.begin(), data.end(), data.begin(), [](std::pair<std::string, std::list<std::string>> elem) -> std::pair<std::string, std::list<std::string>> {elem.second.sort(); return elem;});
Добавлено через 39 секунд
diagon, Так не сработает насколько я помню.
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
10.11.2011, 15:12     Лямбда выражения #19
Цитата Сообщение от ForEveR Посмотреть сообщение
diagon, Так не сработает насколько я помню.
Хм... Почему? Из-за отсутствия -> ?
На gcc нормально компилируется.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.11.2011, 15:14     Лямбда выражения
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
10.11.2011, 15:14     Лямбда выражения #20
diagon, Значит я не прав.
Yandex
Объявления
10.11.2011, 15:14     Лямбда выражения
Ответ Создать тему
Опции темы

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