python里有一个东西,叫map。

它可以实现像这样,对list每个元素进行操作,并返回新的list(python3是迭代器)

像这样

  1. a=list(map(int,input().split()))
  2. b=list(map(lambda x:x*2,a))

遇到这个,我们就会像:c++可不可以也搞一个,对vector每个元素进行操作的函数?

emm,就叫my_map好了。

有了想法,那就开干呗!

老样子,先放成品(完整程序和注释版在后面)

  1. template<typename Ori,typename Func_Type>
  2. auto my_map(Func_Type my_func,vector<Ori> &x){
  3. using return_type = typename result_of<Func_Type(Ori)>::type;
  4. vector<return_type> tmp;
  5. for(auto i :x)
  6. tmp.push_back(my_func(i));
  7. return tmp;
  8. }
  9. int main()
  10. {
  11. auto s=input().split();
  12. cout<<s;
  13. auto a=my_map(my_int,s);//my_int是函数,string转int
  14. cout<<a;
  15. auto b=my_map(Dao_Shu(),a);//Dao_Shu是一个重载了()的类(结构体)
  16. cout<<b;
  17. auto ping_fang=[](int x) { return x*x;};
  18. auto c=my_map(ping_fang,a);//ping_fang是lambda表达式(平方的作用)
  19. cout<<c;
  20. long long sum=0;//同理,可以实现这种操作:求前缀和
  21. auto leijia=[=](int x) mutable{ return sum+=x;};
  22. auto d=my_map(leijia,a);
  23. cout<<d;
  24. }

本文作者XXOY

那个input().split(),和cout<<vector可以看我之前的文章

input().split()

cout<<

这次的代码虽然短,但或许确实是(目前)技术含量最高的一篇了。

0.前置芝士:

(1):c++11的新特性(比如auto、lambda)

(2):c++的template(模板)与函数指针

1.首先考虑要实现的功能:

传一个函数与一个vector,返回对vector中每一个元素使用这个函数的新vector。

于是就有了第一版

  1. template<typename T,typename T2>
  2. vector<T2> my_map(T2 (*co)(T),vector<T> yuan){
  3. vector<T2> x;
  4. for(auto i:yuan)
  5. x.push_back(co(i));
  6. return x;
  7. }

传递一个函数指针进去,然后进行操作。

但这样只能搞普通的函数,不能操纵lambda,会报错。

进行了一番百度、google以后发现lambda本质是一个重载过()的类(某种意义上)

于是有了第二版:

  1. template<typename Ori,typename Func_Type>
  2. auto my_map(Func_Type my_func,vector<Ori> &x){
  3. auto k=my_func(yuan[0]);
  4. vector<decltype(k)> tmp;
  5. for(auto i :x)
  6. tmp.push_back(my_func(i));
  7. return tmp;
  8. }

为什么搞一个k呢?因为那时我不知道如何获取一个函数返回值的类型,只能傻傻的先去操作一下先。

会遇到什么问题呢?空的vector会报错。

遂继续百度(这足足花了两天)。

才知道有种东西叫result_of,专门用来获取返回值类型的。

于是--->第三版

  1. template<typename Ori,typename Func_Type>
  2. auto my_map(Func_Type my_func,vector<Ori> &x){
  3. using return_type = typename result_of<Func_Type(Ori)>::type;
  4. vector<return_type> tmp;
  5. for(auto i :x)
  6. tmp.push_back(my_func(i));
  7. return tmp;
  8. }
  9. //result_of 是获取返回值类型的意思。
  10. //可以不需要T2 (*my_func)(T)像这样定义函数,直接把它当一个类用就行了
  11. //对于lambda:某种意义上,它本质上就是一个重载了()的类

OK,写完,收工。

现在,它可以实现如下骚操作。

  1. auto s=input().split();
  2. //s的类型是vector<string>
  3. cout<<s;
  4. auto a=my_map(my_int,s);
  5. //my_int是函数,string转int
  6. //a的类型是vector<int>
  7. cout<<a;
  8. //Dao_Shu是一个重载了()的类(结构体)
  9. auto b=my_map(Dao_Shu(),a);
  10. //DS是一个类型为Dao_Shu的变量
  11. //也可以auto b=my_map(DS,a);
  12. //b是vector<double>
  13. cout<<b;
  14. auto ping_fang=[](int x) { return x*x;};
  15. //ping_fang是lambda表达式(平方的作用)
  16. auto c=my_map(ping_fang,a);
  17. //c是vector<int>
  18. cout<<c;
  19. long long sum=0;
  20. auto leijia=[=](int x) mutable{ return sum+=x;};
  21. //同理,可以实现这种操作:求前缀和
  22. auto d=my_map(leijia,a);
  23. //d是vector<long long>
  24. cout<<d;

完整代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. //split()和input()的实现
  4. struct mystring:string{//继承string类
  5. mystring() :string() {}
  6. mystring& operator=(const string &c) {
  7. (*this).assign(c);
  8. return *this;
  9. }
  10. vector<string> split(char c=' '){
  11. vector<string> x;
  12. int last=0,len=0;
  13. for(int i=0;i<size();++i)
  14. if(at(i)==c){
  15. x.push_back(substr(last,len));
  16. last=i+1;
  17. len=0;
  18. }
  19. else ++len;
  20. if(last<size())
  21. x.push_back(substr(last,len));
  22. return x;
  23. }
  24. }s;
  25. mystring input(){
  26. mystring s;
  27. getline(cin,s);
  28. return s;
  29. }
  30. //重载cout<<
  31. namespace py_pr{
  32. template<typename T>
  33. inline ostream& out_put(ostream& o,const T & x){
  34. return o<<x;
  35. }
  36. inline ostream& out_put(ostream& o,const string& x){
  37. return o<<"\""<<x<<"\"";
  38. }
  39. inline ostream& out_put(ostream& o,const char* & x){
  40. return o<<"\""<<x<<"\"";
  41. }
  42. inline ostream& out_put(ostream& o,const char & x){
  43. return o<<"\'"<<x<<"\'";
  44. }
  45. template<typename T1,typename T2>
  46. inline ostream& out_put(ostream& o,const pair<T1,T2> & x){
  47. out_put(o,x.first);
  48. o<<": ";
  49. out_put(o,x.second);
  50. return o;
  51. }
  52. }
  53. template<typename T>
  54. ostream& operator<<(ostream &o,vector<T> &x){
  55. o<<"[";
  56. for(auto i=x.begin();i<x.end();++i){
  57. //可以直接for(auto i:x),但是我不知道怎么特判第一个来控制","
  58. if(i!=x.begin()) o<<", ";
  59. py_pr::out_put(o,*i);
  60. }
  61. o<<"]"<<endl;
  62. return o;
  63. }
  64. template<typename Ori,typename Func_Type>
  65. auto my_map(Func_Type my_func,vector<Ori> &x){
  66. using return_type = typename result_of<Func_Type(Ori)>::type;
  67. vector<return_type> tmp;
  68. for(auto i :x)
  69. tmp.push_back(my_func(i));
  70. return tmp;
  71. }
  72. //result_of 是获取返回值类型的意思。
  73. //可以不需要T2 (*my_func)(T)像这样定义函数,直接把它当一个类用就行了
  74. //对于lambda:某种意义上,它本质上就是一个重载了()的类
  75. int my_int(const string x){
  76. return stoi(x);
  77. }
  78. struct Dao_Shu{
  79. double operator() (double x){
  80. return 1.0/x;
  81. }
  82. }DS;
  83. int main()
  84. {
  85. auto s=input().split();
  86. //s的类型是vector<string>
  87. cout<<s;
  88. auto a=my_map(my_int,s);
  89. //my_int是函数,string转int
  90. //a的类型是vector<int>
  91. cout<<a;
  92. //Dao_Shu是一个重载了()的类(结构体)
  93. auto b=my_map(Dao_Shu(),a);
  94. //DS是一个类型为Dao_Shu的变量
  95. //也可以auto b=my_map(DS,a);
  96. //b是vector<double>
  97. cout<<b;
  98. auto ping_fang=[](int x) { return x*x;};
  99. //ping_fang是lambda表达式(平方的作用)
  100. auto c=my_map(ping_fang,a);
  101. //c是vector<int>
  102. cout<<c;
  103. long long sum=0;
  104. auto leijia=[=](int x) mutable{ return sum+=x;};
  105. //同理,可以实现这种操作:求前缀和
  106. auto d=my_map(leijia,a);
  107. //d是vector<long long>
  108. cout<<d;
  109. }

最后的最后Q&A环节:

1.Q:为什么要搞这种东西呢?

A:因为我开心。

2.不能做到的:直接传stoi之类的函数。

原因大概是其中有缺省参数,参数表不匹配。会编译不通过

解决办法:包个壳(感谢@たくやりん 提供的方法)

比如这样int my_int(string x){ return stoi(x); }

更多内容,包括那个input().split(),和cout<<vector可以看我的主页。

input().split()

cout<<

我是XXOY,我们下次再见。

c++实现类似python的map一样,批量操作一个vector的功能【python一样写c++、三】的更多相关文章

  1. 《python解释器源码剖析》第1章--python对象初探

    1.0 序 对象是python中最核心的一个概念,在python的世界中,一切都是对象,整数.字符串.甚至类型.整数类型.字符串类型,都是对象.换句话说,python中面向对象的理念观测的非常彻底,面 ...

  2. python之map、filter、reduce、lambda函数 转

    python之map.filter.reduce.lambda函数  转  http://www.cnblogs.com/kaituorensheng/p/5300340.html 阅读目录 map ...

  3. Python【map、reduce、filter】内置函数使用说明(转载)

    转自:http://www.blogjava.net/vagasnail/articles/301140.html?opt=admin 介绍下Python 中 map,reduce,和filter 内 ...

  4. python基础——map/reduce

    python基础——map/reduce Python内建了map()和reduce()函数. 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Pro ...

  5. 【转】Python 中map、reduce、filter函数

    转自:http://www.blogjava.net/vagasnail/articles/301140.html?opt=admin 介绍下Python 中 map,reduce,和filter 内 ...

  6. [spark][python]Spark map 处理

    map 就是对一个RDD的各个元素都施加处理,得到一个新的RDD 的过程 [training@localhost ~]$ cat names.txtYear,First Name,County,Sex ...

  7. 使用Python实现Map Reduce程序

    使用Python实现Map Reduce程序 起因 想处理一些较大的文件,单机运行效率太低,多线程也达不到要求,最终采用了集群的处理方式. 详细的讨论可以在v2ex上看一下. 步骤 MapReduce ...

  8. python的map函数的使用方法详解以及使用案例(处理每个元素的自增、自减、平方等)

    1.用我们之前学过的求一下平方(只有一个列表) #求平方 num=[1,5,6,2,7,8] a=[] for n in num: a.append(n**2) print (a) C:\python ...

  9. [译]PYTHON FUNCTIONS - MAP, FILTER, AND REDUCE

    map, filter, and reduce Python提供了几个函数,使得能够进行函数式编程.这些函数都拥有方便的特性,他们可以能够很方便的用python编写. 函数式编程都是关于表达式的.我们 ...

  10. python中map()和dict()的用法

    map()用法 map()是python的内置函数,会根据提供的函数对指定序列做映射. 语法: map(func, iter, ...) 其中func为一个功能函数,iter表示可迭代参数序列.map ...

随机推荐

  1. element 表格show-overflow-tooltip的属性设置样式

    在style标签中不要加scoped .el-tooltip__popper { max-width: 60% !important; } .el-tooltip__popper, .el-toolt ...

  2. 【shell脚本实战】脚本#35 分析每个用户使用的磁盘空间大小

    #!/bin/bash #设置 一个变量代表临界值,看看是否能超过这个值,单位是MB MAXDISKUSAGE=20000 #cut -d: -f1,3 /etc/passwd | awk -F: ' ...

  3. 打车起步价8元(3KM以内) 超过3KM,超出的每公里1.2元 超过5KM,超出的每公里1.5元 请在键盘上接收公里数,得出总价。

    import java.util.Scanner; public class Taxi { public static void main(String []agrs){ Scanner s = ne ...

  4. Linux 使用vsftpd服务传输文件

    文件传输协议 FTP是一种在互联网中进行文件传输的协议,基于客户端/服务器模式,默认使用20.21号端口,其中端口20(数据端口)用于进行数据传输,端口21(命令端口)用于接受客户端发出的相关FTP命 ...

  5. oracle SDO_ORDINATE_ARRAY直接展示

    mdsys.sdo_geometry 中SDO_ORDINATE存储的是空间对象的几何节点坐标序列,要想直接展示第一条值出来需要捞出数据 若select t.id,t.shape.sdo_ordina ...

  6. Vue中的样式穿透,修改element-ui组件样式不生效

    在Vue项目中用的比较多的就是组件,为了实现组件的样式模块化.我们通常会在style标签中添加一个scoped属性,这样css样式只能作用于当前的Vue组件.使组件之间的样式相互独立,当调用该组件的时 ...

  7. 当jar包执行时,内嵌的文件找不到时,可以这样解决!

    1.加载是可以加载到的,但是只能是以流的形式存在. 2.如果要按文件进行加载,可以新建一个文件,然后以流的形式写入到新的文件中. 3.加载这个新的文件来进行处理.

  8. Jmeter一、开源软件的崛起

    一.jmeter自身特点: 1.开源,轻量级,更适合自动化和持续集成. 2.学习难度大. 3.资料少.多英文. 二.性能测试工具选型的原则 1.成本: a.工具成本 b.学习成本 2.通信协议: a. ...

  9. QTreewidget勾选功能

    //connect(ui->treeWidget,&QTreeWidget::itemClicked,this,&PushSelectUser::treeItemChanged) ...

  10. Filbeat采集nginx-ingress日志

    一.创建configmap配置文件 注:filebeat6以上版本需要将prospectors改为inputs,paths下指定的nginx-ingress日志路径匹配模式以及hosts指定的kafk ...