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
先来看看一个.NET下的简单查询方式
 
 
var someArray = new int[] { 1, 2, 3, 4 };
var otherArray = someArray.Select(t => t * 2);   
在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 }); 
然后定义 比较(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 }); 
 
SelectMany
 
 
 
SelectMany
 
 
Take
 
 
Array.prototype.take = function (c) {
    return this.slice(0, c);
};  
 
var arr = [1, 2, 3, 4, 5]; 
var res = arr.take(2);
Skip
 
跳过指定数后返回集合数据,使用slice。
 
 
Array.prototype.skip = function (c) {
    return this.slice(c);
}; 
 
var arr = [1, 2, 3, 4, 5]; 
var res = arr.skip(2);  
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
 
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);  
 
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}] 
 
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 
 
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]
 
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;
});    
 
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 });   
 
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;
};  
 
 
 
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;
};  
 
 
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 
 
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  
 
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 
 
 
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] 
 
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 
 
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 
 
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 
 
 
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); });   
 
 
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]  

时间: 2024-10-31 23:17:13

Javascript实现Linq查询方式的相关文章

深度看点Linq查询与性能解析

众人对LINQ查询持有不同的态度,有的说容易实现,有的说难操作,那到底是什么样子呢,笔者特地为此做了一个Linq查询与性能分析,请看下文吧. Orcas(VS2008&Framework3.5)给我们带来了很多令人兴奋的新特性,尤其是LINQ的引进,可以说方便了一大批开发人员和框架设计人员.过去,当我们使用O/RMapping的一些框架时,最担心的应该是复杂的查询和数据库操作的性能问题,那么LINQ在这个方面给我们带来了什么呢?从LINQ查询开始说起吧. 一:LINQ查询: 一个项目中,对数据库

教你如何实现LINQ查询语句

实现LINQ查询语句有三个步骤,他们分别是获取数据源(任何查询的必备工作).创建查询.执行查询 .本文就从这三个方面对实现LINQ查询语句做简单的介绍. 示例: class IntroToLINQ { static void Main() { //获取数据源(此处由一个数组充当) int[] numbers = new int[7]{0,1,2,3,4,5,6}; //创建查询(numQuery 是 IEnumerable 类型) var numQuery = from num in numbe

LINQ 查询语法

        在LINQ中,数据源和查询结果实际上都是IEnumerable<T>或IQueryable<T>类型对象           LINQ主要的功能就是实现查询,LINQ查询存在以下两种形式.           ⑴ Method Synta (查询方法方式):主要利用 System.Linq.Enumerable 类中定义的扩展方法和Lambda 表达式方式进行查询.它提供了一种增强了程序的可读性的语法,易读易写,写时不容易出错.Visual Studio 2010为

mvc4-MVC4中,用LINQ查询两张表的内容,然后显示在列表中

问题描述 MVC4中,用LINQ查询两张表的内容,然后显示在列表中 如题,新手才接触MVC 请高手帮忙解答 .万分感谢 ,PS:不要说把两个实体层写在一个类中.这样太麻烦 而且不方便 解决方案 把两个实体封装在一个model里面,然后在view层里面直接model.每一个实体就行了,你可以试试 解决方案二: 还有一点的是,我不太会json,如果说用json的方式去实现,麻烦上一下源码. 谢谢了 解决方案三: 两张表有关系么?要是有关系 ,设置一下表关系,查询时,只查主键的表,外键的表内容 ,就自

SQL两种简单分页查询方式

                   以前我们或许都用过了linq的skip and take方式进行分页查询,但是很少自己写sql的分页查询,因为大多数时候,我们都是在调用别人的方法.              最近看到一个文档,感觉方法里面实现的分页查询进入数据库调用的时候,实际最底层调用的还是SQL的分页查询,例如,我们用linq写个分页查询,转成sql表达式后发现:                               实际调用的时候,才发现SQL底层是这样进行分页的.      

将不确定变成确定~LINQ查询两种写法,性能没有影响,优化查询应该是“按需查询”

如果在linq中希望进行一对多的复合查询时,请直接在查询中使用join into,或者使用let 关键字,当然在建立实体时动态赋值对于查询的性能也是没有影响的,两次查询结果完成相同 一 :在实体中赋值 var linq = from data in this.GetModel() join data2 in iWebDepartmentsRepository.GetModel() on data.DepartmentID equals data2.DepartmentID select new

pb中一种比较受客户欢迎的查询方式

作者:达通兴电脑科技公司(www.study01job.com) 郭宝利 受欢迎的原因是,这种查询方式很简单,但是功能可不弱.思路如下: 1.构造一个相对通用的窗口,该窗口用来构造查询条件.在该窗口上放置一个数据窗口控件,用户可以在里面输入内容,每个输入项目作为查询条件,不同的项目之间使用OR联结,并且都是模糊查询.该数据窗口中只放置字符类型的列,日期类型和数字类型的可以使用用户对象在窗口中单独放置. 比如,数据窗口中有'姓名'.'工种'.'毕业院校'等列.用户在'姓名'中输入'郭',在'工种'

开源面向对象数据库db4o之旅,第2部分 db4o查询方式

前言 在 db4o 之旅 系列文章的第一部分:初识 db4o 中,作者介绍了 db4o 的历 史和现状,应用领域,以及和 ORM 等的比较.在这篇文章中,作者将会介绍 db4o 的安装.启动以及三种不同的查询方式:QBE(Query by Example).SODA (Simple Object Database Access) 以及 NQ(Native Queries),并分别通 过这三种不同的途径实现了两个关联对象的查询.本文还示范了开发中最经常用 到的几个典型功能的 db4o 实现. 下载

C#3.0 LINQ查询语法

首先来看一个很简单的LINQ查询例子,查询一个int 数组中小于5的数字,并按照大小顺序排列:class Program{    static void Main(string[] args)    {        int[] arr = new int[] { 8, 5, 89, 3, 56, 4, 1, 58 };         var m = from n in arr where n < 5 orderby n select n;        foreach (var n in m