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. Hadoop 免密码登陆(ssh)

    record save here first [root@hadoop .ssh]# ssh-keygen -t rsa -P ''Generating public/private rsa key ...

  2. DNS服务器配置

    导读 DNS(Domain Name Server,域名服务器)是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器.DNS中保存了一张域名(domain ...

  3. Iphone和iPad适配, 横竖屏

    竖屏情况下: [UIScreen mainScreen].bounds.size.width = 320 [UIScreen mainScreen].bounds.size.width = 568 横 ...

  4. mysql数据库性能优化(包括SQL,表结构,索引,缓存)

    优化目标减少 IO 次数IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当 ...

  5. 【数据库】如家汉庭酒店2000万开房数据1.71G/BAK,792M/CSV

    多家连锁酒店使用了某网络有限公司,开发的酒店WiFi管理.认证管理系统.用户在酒店连接开放的WiFi,上网时会被要求通过网页认证,填写相关信息.这个认证不是在酒店服务器完成的,而是在 某公司 的认证服 ...

  6. APScheduler —— Python化的Cron

    APScheduler全程为Advanced Python Scheduler,是一款轻量级的Python任务调度框架.它允许你像Cron那样安排定期执行的任务,并且支持Python函数或任意可调用的 ...

  7. mysql 启动错误

    错误提示如下: 150815 20:24:40 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended150815 20:2 ...

  8. linux expect 简单讲解

    来自http://blog.csdn.net/winstary/archive/2009/08/08/4422156.aspx使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明, ...

  9. 【Hibernate】Hibernate系列7之二级缓存

    二级缓存 7.1.概述 7.2.配置方法

  10. 用数据表创建树_delphi教程

    数据库结构:字段 类型ID 整型 索引(无重复)name 文本father 整型 //tree初始化procedure TForm1.FormActivate(Sender: TObject);var ...