转载:https://www.cnblogs.com/brucemengbm/p/6747457.html
https://blog.youkuaiyun.com/csnd_ayo/article/details/53955689
lambda 表达式能够方便地构造匿名函数,假设你的代码里面存在大量的小函数,而这些函数一般仅仅被调用一次。那么最好还是将他们重构成 lambda 表达式.
C++11 的 lambda 表达式规范例如以下:
[ capture ] ( params ) mutableexceptionattribute -> ret { body } | (1) | |
[ capture ] ( params ) -> ret { body } | (2) | |
[ capture ] ( params ) { body } | (3) | |
[ capture ] { body } | (4) |
当中
- (1) 是完整的 lambda 表达式形式。
- (2) const 类型的 lambda 表达式,该类型的表达式不能改捕获("capture")列表中的值。
- (3)省略了返回值类型的 lambda 表达式。可是该 lambda 表达式的返回类型能够依照下列规则推演出来:
- 假设 lambda 代码块中包括了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。
- 假设没有 return 语句。则类似 void f(...) 函数。
- 省略了參数列表,类似于无參函数 f()。
mutable 修饰符说明 lambda 表达式体内的代码能够改动被捕获的变量。而且能够訪问被捕获对象的 non-const 方法。exception 说明 lambda 表达式是否抛出异常(noexcept
)。以及抛出何种异常,类似于void f()throw(X, Y)。
attribute 用来声明属性。
另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表。详细解释例如以下:
[a,&b]
a变量以值的方式呗捕获,b以引用的方式被捕获。[this]
以值的方式捕获 this 指针。[&]
以引用的方式捕获全部的外部自己主动变量。[=]
以值的方式捕获全部的外部自己主动变量。[]
不捕获外部的不论什么变量。
此外,params 指定 lambda 表达式的參数。
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> c { 1,2,3,4,5,6,7 };
int x = 5;
c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; } ), c.end());
std::cout << "c: ";
for (auto i: c) {
std::cout << i << ' ';
}
std::cout << '\n';
// the type of a closure cannot be named, but can be inferred with auto
auto func1 = [](int i) { return i+4; };
std::cout << "func1: " << func1(6) << '\n';
// like all callable objects, closures can be captured in std::function
// (this may incur unnecessary overhead)
std::function<int(int)> func2 = [](int i) { return i+4; };
std::cout << "func2: " << func2(6) << '\n';
}
std::remove_if 介绍
Remove_if的等效操作
template < class ForwardIterator, class Predicate >
ForwardIterator remove_if ( ForwardIterator first, ForwardIterator last,
Predicate pred )
{
ForwardIterator result = first;
for ( ; first != last; ++first)
if (!pred(*first)) *result++ = *first;
return result;
}
原型:
template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
first = std::find_if(first, last, p);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!p(*i))
*first++ = std::move(*i);
return first;
}
template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first) {
if (p(*first)) {
return first;
}
}
return last;
}
前两个参数:
给他一个迭代的起始位置和这个起始位置所对应的停止位置。 例如下方函数中的 str.begin(), str.end()
最后一个参数:
传入一个回调函数,如果 回调函数函数返回真,则将当前所指向的参数,移到尾部(不稳定的数据移动)例如 下方的 Lambda 表达式 如果 n == find_str 这条命题为真则执行操作。
返回值:
被移动区域的首个元素 iterator
头文件 #include <algorithm>
这个函数不负责删除工作。所以他一般与 erase 成对出现
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
std::vector<std::string> str = { "Name", "1", "2", "3 ", "4", "5", "6", "7", "Name"};
auto find_str = "Name";
auto sd = std::remove_if(str.begin(), str.end(), [find_str](std::string n) { return n == find_str; });
str.erase(sd, str.end());
for(auto i:str)
std::cout << i << ' ';//1 2 3 4 5 6 7
}
std::unordered_map::operator[]
If k matches the key of an element in the container, the function returns a reference to its mapped value.
函数对象(Function Object)谓词
类中重载函数的调用"()", 使类可以被调用, 并且传入算法谓词中, 进行使用.
- /*Function Object*/
- class LargerString {
- public:
- bool operator() (const std::string& a, const std::string& b) {
- return a.size() > b.size();
- }
- };
- ......
- std::stable_sort(sv.begin(), sv.end(), LargerString());
Leetcode451. 对字符出现频率进行排序
转载:https://blog.youkuaiyun.com/obrcnh/article/details/78068496
通过上面几个例子我们可以发现,题目要求我们按照字符出现频率从高到低进行排序,大小写区分。看到字符出现频率,很自然地就想到用unordered_map哈希表来存储每个字符出现的次数。然后通过对整个哈希表进行排序,最后将其进行输出。
但是这里有一个问题,就是stl的sort算法只能对线性序列容器进行排序(即vector,list,deque)。所以我们这里就要设法将存储在哈希表里面的内容转移到vector这些容器中了。这里由于哈希表存储的是key-value对,所以vector应该声明成pair某种模板类型,这样在vector中才能通过value找到相对应的key值。
在将键值对全部插入到vector之后,就要对value值进行排序了。stl的sort函数有三个参数,其中第三个参数是可选的,是一个返回值类型可转化为bool的函数,表示sort的方式。如果我们不传入第三个参数,那么sort完成后输出的结果就是按ascii值从小到大进行排序的结果。因此,在这里有必要传入第三个参数。
这里用到了c++11的lambda表达式,它是一种函数式编程的写法,其中[]表示要捕获的内容,()表示函数传入的参数。这里函数体内容就很简单了,只需比较两个参数对应的value值,这样我们就确定了sort排序的方式,问题就解决了。
class Solution {
public:
string frequencySort(string s) {
string str = "";
unordered_map<char, int> iMap;
vector<pair<char, int>> vtMap;
for (int i = 0; i < s.size(); i++) {
iMap[s[i]]++;
}
for (auto it = iMap.begin(); it != iMap.end(); it++) {
vtMap.push_back(make_pair(it->first, it->second));
}
sort(vtMap.begin(), vtMap.end(), [](const pair<int, int>& x, const pair<int, int>& y) -> int {
return x.second > y.second;
});
for (auto it = vtMap.begin(); it != vtMap.end(); it++) {
for (int i = 0; i < it->second; i++) {
str += it->first;
}
}
return str;
}
};