C一份Linq to object的C实现.docx
- 文档编号:12221016
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:13
- 大小:17.66KB
C一份Linq to object的C实现.docx
《C一份Linq to object的C实现.docx》由会员分享,可在线阅读,更多相关《C一份Linq to object的C实现.docx(13页珍藏版)》请在冰豆网上搜索。
C一份Linqtoobject的C实现
[C++]一份Linqtoobject的C++实现
一份Linqtoobject的C++实现
几个月的构想+0.5小时的设计+4小时的linq.h编码+3小时的测试编码。
大量使用C++11的特性,在GCC4.7.2下编译通过。
关于实现相关的描述就不说了,我表达能力差,恐怕讲清楚还需要好几个小时。
具体使用参见测试码。
上代码:
(1)linq.h
ViewCode
(2)测试代码main.cpp(比我的代码更烂的是我的英语)
#include"pch.h"
#include"linq.h"
#include<vector>
#include<string>
#include<algorithm>
template<typenameT>
voidprintC(constT&v)
{
for(autoi:
v)cout<<i<<',';
cout<<endl;
}
template<typenameT>
voidprint(constT&v)
{
cout<<v<<endl;
}
boolstartsWith(conststd:
:
string&s,conststd:
:
string&prefix)
{
returns.find(prefix)==0;
}
voidfeatureTest()
{
//1.standard
{
autoquery=range(10)
.where([](inti){returni%2;})
.select([](inti){returni+1;});
autoref={2,4,6,8,10};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//2.deferredrange
{
assert(range(123LL,1000000000000LL).first()==123);
}
//3.deferredaction
{
intselectCnt=0;
autoquery=range(1,1000)
.where([](inti){returni%2==0;})
.select([&selectCnt](inti)
{
++selectCnt;
returni;
})
.where([](inti){returni%4==0;})
.head
(2);
autoquery2=query;
for(autoi:
query){}
assert(selectCnt==4);
for(autoi:
query2){}
assert(selectCnt==8);
}
//4.copysemantic
{
autoquery=range(10).head(5);
autoquery2=query;
autoref={0,1,2,3,4};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
assert(std:
:
equal(ref.begin(),ref.end(),query2.begin()));
autoiter=query.begin();
++iter;
autoiter2=iter;
ref={1,2,3,4};
assert(std:
:
equal(ref.begin(),ref.end(),iter));
assert(std:
:
equal(ref.begin(),ref.end(),iter2));
}
//5.alwaysreferencetheneweastdataofdataSource
{
std:
:
vector<std:
:
string>dataSrc{"A_abc","A_def","B_abc","B_def"};
autoquery=from(dataSrc)
.head(3)
.where([](conststd:
:
string&s){returnstartsWith(s,"B_");});
autoref={"B_abc"};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
dataSrc.clear();
dataSrc.shrink_to_fit();
dataSrc={"B#_abc","B_123","B_1234","B_321","B_111"};
ref={"B_123","B_1234"};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//6.invoketheoperatornewasleastaspossible
{
}
//7.youcanusequeryafterthedataSourcehasbeendestroyed,bytheuseof'reserve'
{
Enumerable<int>query;
{
std:
:
vector<int>v{1,2,3,4};
//query=from(v).select([](inti){returni%2;});
query=from(v).reserve().select([](inti){returni%2;});
autoref={1,0,1,0};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
autoref={1,0,1,0};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//8.addactiontoanexistquery
{
autoquery=range(10).where([](inti){returni<5;});
autoref={0,1,2,3,4};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
autoquery2=query.select([](inti){returni*i;});
ref={0,1,4,9,16};
assert(std:
:
equal(ref.begin(),ref.end(),query2.begin()));
}
}
voidfunctionTest()
{
//1.from,select,where,cast
{
inta[]{5,6,7,8,9};
autoquery=from(a)
.where([](inti){returni%3;})
.select([](inti){returni*i;});
autoref={25,49,64};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//2.range,all,any
{
assert(range(10).all([](inti){returni>=0;}));
assert(!
range(10).all([](inti){returni>0;}));
assert(from(std:
:
vector<std:
:
string>{"_a","b"})
.any([](conststd:
:
string&s){returnstartsWith(s,"_");}));
assert(!
from(std:
:
vector<std:
:
string>{"@a","b"})
.any([](conststd:
:
string&s){returnstartsWith(s,"_");}));
}
//3.cast,average
{
assert(range(1,5).average()==2);
assert(range(1,5).cast<float>().average()==2.5);
}
//4.contain,count
{
inta[]{1,2,1,1,3,2,};
assert(from(a).contain(3));
assert(!
from(a).contain(4));
assert(from(a).count
(1)==3);
assert(from(a).count([](inti){returni%2;})==4);
}
//5.first,last,head,tail
{
inta[]{3,5,7,9,11};
assert(from(a).first()==3);
assert(from(a).last()==11);
autoref={3,5};
autoquery=from(a).head
(2);
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
ref={7,9,11};
query=from(a).tail(3);
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//6.groupBy
{
autoquery=range(10).groupBy([](inti){returni%3;});
intrefs[][4]={
{0,3,6,9},
{1,4,7,},
{2,5,8,},
};
intn=0;
for(autoi:
query){
assert(i.first==refs[n][0]);
assert(std:
:
equal(i.second.begin(),i.second.end(),refs[n]));
++n;
}
assert(n==3);
}
//7.takeUntil,skipUntil
{
autoquery=range(10).takeUntil([](inti){returni>5;});
autoref={0,1,2,3,4,5};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
query=range(10).skipUntil([](inti){returni>5;});
ref={6,7,8,9};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//8.max,min
{
inta[]{3,2,5,8,10,-3};
assert(from(a).min()==-3);
assert(from(a).max()==10);
}
//9.reduce
{
assert(range(1,11).reduce([](inta,intb){returna+b;})==55);
assert(range(1,11).reduce([](inta,intb){returna*b;},0)==0);
assert(range(1,11).reduce([](inta,intb){returna*b;},1)==3628800);
}
//10.unique,sort,random
{
inta[]{3,5,5,4,2,1,2};
autoquery=from(a).unique();
autoref={3,5,4,2,1};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
ref={5,4,3,2,1};
query=query.sort().sort([](inta,intb){returna>b;});
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
query=query.random();
assert(!
std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
//11.intersect,_union
{
inta[]{3,5,11};
autoquery=range(10).intersect(from(a));
autoref={3,5};
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
ref={3,4,5,6};
query=query._union(range(4,7));
assert(std:
:
equal(ref.begin(),ref.end(),query.begin()));
}
}
intmain()
{
featureTest();
functionTest();
}
为什么不把它提交到github之类的专门代码仓库?
一则我没有用过,二则,这种代码是我的write-only构想实践码,不提供后续维护的:
)
分类:
C/C++
绿色通道:
好文要顶
关注我
收藏该文与我联系Scan.
关注-11
粉丝-32+加关注1
0
(请您对文章做出评价)上一篇:
[图形图像]一次光线追踪的尝试
下一篇:
[C++]assert的加强版——Ensure的简易实现posted@2012-10-2023:
28Scan.阅读(1116)评论(17)编辑收藏评论列表
#1楼[楼主]2012-10-2121:
20Scan.
实现linq的延迟特性的最佳设施是c#的yieldreturn,我老早就考虑用lambda表达式作为yield的替代方案。
最后终于在python和c++中各实现了一次linq。
支持(0)反对(0)
#2楼2012-10-2312:
45代震军
有意思支持(0)反对(0)
#3楼2012-10-2312:
55陈梓瀚(vczh)
尽管我只看了testcase,我还是觉得你的接口还是做得很漂亮的,再接再厉。
支持(0)反对(0)
#4楼[楼主]2012-10-2313:
03Scan.
@陈梓瀚(vczh)
谢谢老大鼓励!
!
!
!
支持(0)反对(0)
#5楼2012-12-2911:
06yesme
vs2010通不过支持(0)反对(0)
#6楼[楼主]2012-12-2911:
14Scan.
@yesme
所以才说需要GCC4.7.2以上啊。
vc2010支持的c++11特性太少了。
支持(0)反对(0)
#7楼2013-03-3012:
45yu_yu
可以看看这个支持(0)反对(0)
#8楼2013-05-3015:
46qicosmos
支持!
挺好的。
有没有linqtosql的c++版本呢支持(0)反对(0)
#9楼2013-06-0817:
00qicosmos
挺好的,能否把编程思想说一下?
支持(0)反对(0)
#10楼[楼主]2013-06-1215:
12Scan.
@qicosmos
我记不太清了,不过才几百行代码,感兴趣的话自己看看吧。
特别的注意减少内存分配和延迟迭代就是了。
上面那个7楼的方案更专业。
支持(0)反对(0)
#11楼2013-06-1416:
32qicosmos
大概思路是,先将集合转成枚举器,枚举器中保存闭包,在外面移动迭代器重复调用闭包,闭包中嵌套了闭包,层层调用实现方法的组合。
其实有更简单的方案,我也实现了一个c++linq。
支持(0)反对(0)
#12楼2013-06-1417:
03qicosmos
c++中实现yield,似乎比较麻烦啊,boost.coroutine库中有宏定义了一个yield,但是用起来有点麻烦,有更好用的yield吗?
支持(0)反对(0)
#13楼[楼主]2013-06-1417:
08Scan.
@qicosmos
你的方案的url呢?
参考一下呵呵支持(0)反对(0)
#14楼2013-06-1417:
16qicosmos
不好意思,公司内部的项目中用到了,不方便公开。
支持(0)反对(0)
#15楼[楼主]2013-06-1417:
28Scan.
@qicosmos
嗯好的,理解支持(0)反对(0)
#16楼2013-12-0611:
12共享天涯
恕我眼拙,对模板这一块不太熟。
博主能否说一下你的这个linq实现有哪些缺陷之类,
这样大家如果愿意尝试使用时也可以避免一下。
支持(0)反对(0)
#17楼[楼主]2013-12-0611:
15Scan.
@共享天涯
玩具,非产品级,请尝试更好的方案
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 一份Linq to object的C 实现 一份 Linq object