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.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

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查询方式的更多相关文章

  1. xamarin studio And linq 查询方式分析

    在 Windows 操作系统可以正常读取网络上的 https 数据流,在 Linux 操作系统中会失败:http://www.cnblogs.com/skyivben/archive/2012/03/ ...

  2. LINQ查询数组里面是否包含某值

    #region linq to 数组            //定义数组,并初始化            string [] array = new string []{"Juan" ...

  3. C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询

    1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...

  4. C#基础:LINQ 查询函数整理

    1.LINQ 函数   1.1.查询结果过滤 :where() Enumerable.Where() 是LINQ 中使用最多的函数,大多数都要针对集合对象进行过滤,因此Where()在LINQ 的操作 ...

  5. Linq查询表达式

    目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. ...

  6. LINQ 查询表达式(C# 编程指南)

    语言集成查询 (LINQ) 是一组技术的名称,这些技术建立在将查询功能直接集成到 C# 语言(以及 Visual Basic 和可能的任何其他 .NET 语言)的基础上.  借助于 LINQ,查询现在 ...

  7. LINQ查询返回DataTable类型

    个人感觉Linq实用灵活性很大,参考一篇大牛的文章LINQ查询返回DataTable类型 http://xuzhihong1987.blog.163.com/blog/static/267315872 ...

  8. atitit. 集合groupby 的实现(2)---自定义linq查询--java .net php

    atitit.  集合groupby 的实现(2)---自定义linq查询--java .net php 实现方式有如下 1. Linq的实现原理流程(ati总结) 1 2. groupby  与 事 ...

  9. Linq查询简介

    查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此, ...

随机推荐

  1. 聊下并发和Tomcat线程数(Updated)

    最近一直在解决线上一个问题,表现是: Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看很多请求超过了1s. 服务器性能很好,Tomcat版本是 ...

  2. undefined与null的区别

    最近在默默的看面试题,其中有一个题目就是“undefined和null的区别”,突然意识到自己从未关注过这个问题,心中莫名有种急躁的感觉,百度一下发现阮大神的一篇文章(http://www.ruany ...

  3. FZU2127:养鸡场

    Problem Description Jason买来了n米长的竹篱笆,打算将n米长的竹篱笆所实用来围成一个三角形的养鸡场.为方便起见.养鸡场三条边的长度都为正整数. 同一时候.他想让自己的养鸡场看起 ...

  4. HDU 4858 项目管理(邻接表 暴力模拟)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4858 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的! 两个节点间可 ...

  5. [ruby on rails] 跟我学之(7)创建数据

    通过form来创建数据,本章节将会涉及内容:创建form,用户重导向,渲染views 和 flash消息. 1. views初步 编辑 app/views/posts/index.html.erb这个 ...

  6. nc 常用命令

    nc(NetCat),在网络工具中有”瑞士军刀”的美誉,它短小精悍,功能强大,下面分享一些我平时经常用到的功能,更多的功能请google之. 1.基本参数想要连接到某处: nc [-options] ...

  7. ethtool 命令详解

    命令描述: ethtool 是用于查询及设置网卡参数的命令. 使用概要:ethtool ethx       //查询ethx网口基本设置,其中 x 是对应网卡的编号,如eth0.eth1等等 转自: ...

  8. 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 ...

  9. java类的封装 继承 多态

    1.猜数字小游戏 package cn.jiemoxiaodi_02; import java.util.Scanner; /** * 猜数字小游戏 * * @author huli * */ pub ...

  10. 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 [题目] ...