zoukankan      html  css  js  c++  java
  • 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.union = Array.prototype.concat; 

    先来看看一个.NET下的简单查询方式

    var someArray = new int[] { 1, 2, 3, 4 };
    var otherArray = someArray.Select(t => t * 2);   
    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
  • 相关阅读:
    刷过算法题汇总
    List
    PHP+JQUEY+AJAX实现分页
    关于响应式布局
    bootscript/javascript组件
    关于H5框架之Bootstrap的小知识
    SEO优化---学会建立高转化率的网站关键词库
    jQuery Mobile学习笔记
    ANGULAR $HTTP请求
    css3 transition
  • 原文地址:https://www.cnblogs.com/yzp12sina/p/3525098.html
Copyright © 2011-2022 走看看