Javascript实现Linq查询方式
Linq是.net平台一个重要的技术,全称Language Integrated Query。通过构建快速查询语句,可快速从数据库或集合中筛选数据集、以查询数据库相同的方式操作内存数据。
在ECMAScript 5th以后的版本中,Javascript实现了有限的有限的Linq查询方式,包括forEach, every, some, filter, map, reduce and reduceRight.
首先需要说明,以上这些方法并不是跨浏览器的,对版本有相应的限制。我们知道Linq的对象需要实现Enumerable接口,本篇文章主要介绍使用JS模拟实现C# 中的Linq查询,包括 聚集查询、迭代查询、条件查询、构建Selector查询器等。
Javascript本质上并不支持类的继承,通过属性的继承可实现类的面向对象的功能,所以这也被认为是面向对象的一种方式,这就意味着可以使用它的属性构建更多面向对象的接口。例如Array,它是继承自Array.prototype 。如果更改了Array.prototype,那么基于这个属性继承的数组必然会变化。有了这些依据后开始构建我们的Linq功能。
举个例子,JS API不支持union方法,但支持concat方法合并数据。
Array.prototype.union = Array.prototype.concat;
先来看看一个.NET下的简单查询方式
var someArray = new int[] { , , , };
var otherArray = someArray.Select(t => t * );
c# Select
在C#下使用查询数据时使用的是Select,使用一个 Delegate 构建查询。在这个例子中,我们使用了 t => t * 2 是一个 Lambda表达式。 将这个功能嫁接到JS下,定义一个function(){}
JS下的Select查询可以是这样
var someArray = [1, 2, 3, 4];
var otherArray = someArray.select(function (t) { return t * 2 });
JS Select
以下我们将一一实现JS的 比较(、条件(EqualityComparer)、排序(SortComparer)Predicate)、查询器(Selector)
- Javascript Linq 查询器
Select
遍历元素下的每一个元素,调用JS.Call方法返回数据。
Array.prototype.select = Array.prototype.map || function (selector, context) {
context = context || window;
var arr = [];
var l = this.length;
for (var i = 0; i < l; i++)
arr.push(selector.call(context, this[i], i, this));
return arr;
};
var arr = [1, 2, 3, 4, 5];
var doubled = arr.select(function(t){ return t * 2 });
Select
SelectMany
Array.prototype.selectMany = function (selector, resSelector) {
resSelector = resSelector || function (i, res) { return res; };
return this.aggregate(function (a, b, i) {
return a.concat(selector(b, i).select(function (res) { return resSelector(b, res) }));
}, []);
};
var arr = [{Name:"A", Values:[1, 2, 3, 4]}, {Name:"B", Values:[5, 6, 7, 8]}];
var res1 = arr.selectMany(function(t){ return t.Values });
var res2 = arr.selectMany(function(t){ return t.Values }, function(t, u){ return {Name:t.Name, Val:u}});
Take
Array.prototype.take = function (c) {
return this.slice(0, c);
};
var arr = [1, 2, 3, 4, 5];
var res = arr.take(2);
Take
Skip
跳过指定数后返回集合数据,使用slice。
Array.prototype.skip = function (c) {
return this.slice(c);
};
var arr = [1, 2, 3, 4, 5];
var res = arr.skip(2);
Skip
First
返回序列的第一个元素,如果没有元素,可以指定一个默认元素。
Array.prototype.first = function (predicate, def) {
var l = this.length;
if (!predicate) return l ? this[0] : def == null ? null : def;
for (var i = 0; i < l; i++)
if (predicate(this[i], i, this))
return this[i];
return def == null ? null : def;
};
var arr = [1, 2, 3, 4, 5];
var t1 = arr.first();
var t2 = arr.first(function(t){ return t > 2 });
var t3 = arr.first(function(t){ return t > 10 }, 10); //默认值是10
First
Union
合并两个集合中的数据,使用concat,不合并重复数据。
Array.prototype.union = function (arr) {
return this.concat(arr).distinct();
};
var arr1 = [1, 2, 3, 4, 5];
var arr2 = [5, 6, 7, 8, 9];
var res = arr1.union(arr2);
Union
Distinct
找出不重复的数据。当有重复元素是只push一个元素进集合。
Array.prototype.distinct = function (comparer) {
var arr = [];
var l = this.length;
for (var i = 0; i < l; i++) {
if (!arr.contains(this[i], comparer))
arr.push(this[i]);
}
return arr;
};
var arr1 = [1, 2, 2, 3, 3, 4, 5, 5];
var res1 = arr.distinct(); // [1, 2, 3, 4, 5]
var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:1}];
var res2 = arr2.distinct(function(a, b){ return a.Val == b.Val }); //返回[{Name:"A", Val:1}]
Distinct
IndexOf
查找指定的值第一次出现的位置。
Array.prototype.indexOf = Array.prototype.indexOf || function (o, index) {
var l = this.length;
for (var i = Math.max(Math.min(index, l), 0) || 0; i < l; i++)
if (this[i] === o) return i;
return -1;
};
var arr = [1, 2, 3, 4, 5];
var index = arr.indexOf(2); // 1
IndexOf
Remove
从集合中移除指定元素。
Array.prototype.remove = function (item) {
var i = this.indexOf(item);
if (i != -1)
this.splice(i, 1);
};
var arr = [1, 2, 3, 4, 5];
arr.remove(2); // [1, 3, 4, 5]
Remove
OrderBy
Array.prototype.orderBy = function (selector, comparer) {
comparer = comparer || DefaultSortComparer;
var arr = this.slice(0);
var fn = function (a, b) {
return comparer(selector(a), selector(b));
};
arr.thenBy = function (selector, comparer) {
comparer = comparer || DefaultSortComparer;
return arr.orderBy(DefaultSelector, function (a, b) {
var res = fn(a, b);
return res === 0 ? comparer(selector(a), selector(b)) : res;
});
};
arr.thenByDescending = function (selector, comparer) {
comparer = comparer || DefaultSortComparer;
return arr.orderBy(DefaultSelector, function (a, b) {
var res = fn(a, b);
return res === 0 ? -comparer(selector(a), selector(b)) : res;
});
};
return arr.sort(fn);
};
var arr = [{Name:"A", Val:1}, {Name:"a", Val:2}, {Name:"B", Val:1}, {Name:"C", Val:2}];
var res1 = arr.orderBy(function(t){ return t.Name });
var res2 = arr.orderBy(function(t){ return t.Name }, function(a, b){
if(a.toUpperCase() > b.toUpperCase()) return 1;
if(a.toUpperCase() < b.toUpperCase()) return -1;
return 0;
});
OrderBy
OrderByDescending
Array.prototype.orderByDescending = function (selector, comparer) {
comparer = comparer || DefaultSortComparer;
return this.orderBy(selector, function (a, b) { return -comparer(a, b) });
};
var arr = [{Name:"A", Val:1}, {Name:"a", Val:2}, {Name:"B", Val:1}, {Name:"C", Val:2}];
var res = arr.orderByDescending(function(t){ return t.Name });
OrderByDescending
GroupBy
Array.prototype.groupBy = function (selector, comparer) {
var grp = [];
var l = this.length;
comparer = comparer || DefaultEqualityComparer;
selector = selector || DefaultSelector;
for (var i = 0; i < l; i++) {
var k = selector(this[i]);
var g = grp.first(function (u) { return comparer(u.key, k); });
if (!g) {
g = [];
g.key = k;
grp.push(g);
}
g.push(this[i]);
}
return grp;
};
var arr = [{Name:"A", Val:1}, {Name:"B", Val:1}, {Name:"C", Val:2}, {Name:"D", Val:2}];
var res = arr.groupBy(function(t){ return t.Val });
// [[{Name:"A", Val:1}, {Name:"B", Val:1}], [{Name:"C", Val:2}, {Name:"D", Val:2}]]
res.forEach(function(t){
console.log("Key: " + t.key, "Length: " + t.length);
});
GroupBy
- Javascript Linq 聚合
Min
Array.prototype.min = function (s) {
s = s || DefaultSelector;
var l = this.length;
var min = s(this[0]);
while (l-- > 0)
if (s(this[l]) < min) min = s(this[l]);
return min;
};
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
var min1 = arr.min(); // 1
var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
var min2 = arr2.min(function(t){ return t.Val }); // 1
Min
Max
Array.prototype.max = function (s) {
s = s || DefaultSelector;
var l = this.length;
var max = s(this[0]);
while (l-- > 0)
if (s(this[l]) > max) max = s(this[l]);
return max;
};
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
var max1 = arr.max(); // 8
var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
var max2 = arr2.max(function(t){ return t.Val }); // 2
Max
Sum
Array.prototype.sum = function (s) {
s = s || DefaultSelector;
var l = this.length;
var sum = 0;
while (l-- > 0) sum += s(this[l]);
return sum;
};
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
var sum1 = arr.sum(); // 36
var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
var sum2 = arr2.sum(function(t){ return t.Val }); // 3
Sum
- Javascript Linq 条件查询
Where
Array.prototype.where = Array.prototype.filter || function (predicate, context) {
context = context || window;
var arr = [];
var l = this.length;
for (var i = 0; i < l; i++)
if (predicate.call(context, this[i], i, this) === true) arr.push(this[i]);
return arr;
};
var arr = [1, 2, 3, 4, 5];
var res = arr.where(function(t){ return t > 2 }) ; // [3, 4, 5]
Where
Any
Array.prototype.any = function (predicate, context) {
context = context || window;
var f = this.some || function (p, c) {
var l = this.length;
if (!p) return l > 0;
while (l-- > 0)
if (p.call(c, this[l], l, this) === true) return true;
return false;
};
return f.apply(this, [predicate, context]);
};
var arr = [1, 2, 3, 4, 5];
var res1 = arr.any(); // true
var res2 = arr.any(function(t){ return t > 5 }); // false
Any
All
Array.prototype.all = function (predicate, context) {
context = context || window;
predicate = predicate || DefaultPredicate;
var f = this.every || function (p, c) {
return this.length == this.where(p, c).length;
};
return f.apply(this, [predicate, context]);
};
var arr = [1, 2, 3, 4, 5];
var res = arr.all(function(t){ return t < 6 }); // true
All
Contains
Array.prototype.contains = function (o, comparer) {
comparer = comparer || DefaultEqualityComparer;
var l = this.length;
while (l-- > 0)
if (comparer(this[l], o) === true) return true;
return false;
};
var arr1 = [1, 2, 3, 4, 5];
var res1 = arr.contains(2); // true
var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:1}];
var res2 = arr2.contains({Name:"C", Val:1}, function(a, b){ return a.Val == b.Val }) ; // true
Contains
- Javasciprt Linq 迭代
ForEach
Array.prototype.forEach = Array.prototype.forEach || function (callback, context) {
context = context || window;
var l = this.length;
for (var i = 0; i < l; i++)
callback.call(context, this[i], i, this);
};
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(t){ if(t % 2 ==0) console.log(t); });
ForEach
DefaultIfEmpty
Array.prototype.defaultIfEmpty = function (val) {
return this.length == 0 ? [val == null ? null : val] : this;
};
var arr = [1, 2, 3, 4, 5];
var res = arr.where(function(t){ return t > 5 }).defaultIfEmpty(5); // [5]
DefaultIfEmpty
Javascript实现Linq查询方式的更多相关文章
- xamarin studio And linq 查询方式分析
在 Windows 操作系统可以正常读取网络上的 https 数据流,在 Linux 操作系统中会失败:http://www.cnblogs.com/skyivben/archive/2012/03/ ...
- LINQ查询数组里面是否包含某值
#region linq to 数组 //定义数组,并初始化 string [] array = new string []{"Juan" ...
- C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询
1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...
- C#基础:LINQ 查询函数整理
1.LINQ 函数 1.1.查询结果过滤 :where() Enumerable.Where() 是LINQ 中使用最多的函数,大多数都要针对集合对象进行过滤,因此Where()在LINQ 的操作 ...
- Linq查询表达式
目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...
- LINQ 查询表达式(C# 编程指南)
语言集成查询 (LINQ) 是一组技术的名称,这些技术建立在将查询功能直接集成到 C# 语言(以及 Visual Basic 和可能的任何其他 .NET 语言)的基础上. 借助于 LINQ,查询现在 ...
- LINQ查询返回DataTable类型
个人感觉Linq实用灵活性很大,参考一篇大牛的文章LINQ查询返回DataTable类型 http://xuzhihong1987.blog.163.com/blog/static/267315872 ...
- atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php
atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby 与 事 ...
- Linq查询简介
查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此, ...
随机推荐
- 聊下并发和Tomcat线程数(Updated)
最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s. 服务器性能很好,Tomcat版本是 ...
- undefined与null的区别
最近在默默的看面试题,其中有一个题目就是“undefined和null的区别”,突然意识到自己从未关注过这个问题,心中莫名有种急躁的感觉,百度一下发现阮大神的一篇文章(http://www.ruany ...
- FZU2127:养鸡场
Problem Description Jason买来了n米长的竹篱笆,打算将n米长的竹篱笆所实用来围成一个三角形的养鸡场.为方便起见.养鸡场三条边的长度都为正整数. 同一时候.他想让自己的养鸡场看起 ...
- HDU 4858 项目管理(邻接表 暴力模拟)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的! 两个节点间可 ...
- [ruby on rails] 跟我学之(7)创建数据
通过form来创建数据,本章节将会涉及内容:创建form,用户重导向,渲染views 和 flash消息. 1. views初步 编辑 app/views/posts/index.html.erb这个 ...
- nc 常用命令
nc(NetCat),在网络工具中有”瑞士军刀”的美誉,它短小精悍,功能强大,下面分享一些我平时经常用到的功能,更多的功能请google之. 1.基本参数想要连接到某处: nc [-options] ...
- ethtool 命令详解
命令描述: ethtool 是用于查询及设置网卡参数的命令. 使用概要:ethtool ethx //查询ethx网口基本设置,其中 x 是对应网卡的编号,如eth0.eth1等等 转自: ...
- Convert Sorted Array to Binary Search Tree With Minimal Height
Given a sorted (increasing order) array, Convert it to create a binary tree with minimal height. Exa ...
- java类的封装 继承 多态
1.猜数字小游戏 package cn.jiemoxiaodi_02; import java.util.Scanner; /** * 猜数字小游戏 * * @author huli * */ pub ...
- 59. 总结篇:数组中N(n=1,2,3)个只出现一次的数字[find N numbers which appear only once in array]
[本文链接] http://www.cnblogs.com/hellogiser/p/find-n-numbers-which-appear-only-once-in-array.html [题目] ...