模块: linq

js版的linq查询,类似 LINQ C#,对数组进行的扩展。引用自LINQJS

Selectors

Select

select(selector:(item) => item)

将数组中的每一个元素转换为新的数组,等同于Array.map

var arr = [1, 2, 3, 4, 5];
// 结果: [2, 4, 6, 8, 10]
var doubled = arr.select(function(t){ return t * 2 });

SelectMany

selectMany(selector:(item) => item , [resultSelector:(item,value) => item])

将多个数组的每个元素投影到一个数组,并序列为一个展平数组。

// 对象数组
var arr = [{Name:"A", Values:[1, 2, 3, 4]}, {Name:"B", Values:[5, 6, 7, 8]}];
// 使用默认结果选择器
// 结果: [1, 2, 3, 4, 5, 6, 7, 8]
var res1 = arr.selectMany(function(t){ return t.Values });
// 使用自定义结果选择器
// 结果: [{"Name":"A","Val":1},{"Name":"A","Val":2},...,{"Name":"B","Val":8}]
var res2 = arr.selectMany(function(t){ return t.Values }, function(t, u){ return {Name:t.Name, Val:u}});

// 二维数组
var arr2 = [[1, 2, 3, 4], [5, 6, 7, 8]]; 
// 使用默认结果选择器
// 结果: [1, 2, 3, 4, 5, 6, 7, 8]
var res1 = arr2.selectMany(function(t){ return t});
// 使用自定义结果选择器
// 结果: [{"Val":1},{"Val":2},{"Val":3},{"Val":4},{"Val":5},{"Val":6},{"Val":7},{"Val":8}]
var res2 = arr2.selectMany(function(t){ return t }, function(t, u){ return {Val:u}});

Take

take(count:number)

从数组的开始返回指定数量的连续元素,等同于Array.slice(0, count)。

var arr = [1, 2, 3, 4, 5];
// 结果: [1, 2]  
var res = arr.take(2);

Skip

skip(start:number[, end:number])

绕过数组中指定数量的元素,然后返回其余元素,等同于Array.splice。

var arr = [1, 2, 3, 4, 5];
// 结果: [3, 4, 5]
var res = arr.skip(2);
// 结果: [2, 3, 4]
var res1 = arr.skip(1,4);

First

first(selector:(item, index, array) => boolean[, def:any])

返回数组的第一个元素。

var arr = [1, 2, 3, 4, 5];
// 结果: 1
var t1 = arr.first();
// 使用比较
// 结果: 3
var t2 = arr.first(function(t){ return t > 2 });  
// 使用比较和默认值:10,默认值是指在没有满足条件的元素时输出的值
// 结果: 10,找不到满足条件的元素,返回默认值
var t3 = arr.first(function(t){ return t > 10 }, 10);

Last

last(selector:(item, index, array) => boolean[, def:any])

返回数组的最后一个元素。

var arr = [1, 2, 3, 4, 5];
// 结果: 5
var t1 = arr.last();
// 使用比较
// 结果: 5
var t2 = arr.last(function(t){ return t > 2 });
// 使用比较和默认值:10,默认值是指在没有满足条件的元素时输出的值
// 结果: 10,找不到满足条件的元素,返回默认值
var t3 = arr.last(function(t){ return t > 10 }, 10);

Union

union(arr:array)

合并两个数组。

var arr1 = [1, 2, 3, 4, 5];
var arr2 = [5, 6, 7, 8, 9];
// 结果: [1, 2, 3, 4, 5, 6, 7, 8, 9]
var res = arr1.union(arr2);

Intersect

intersect(arr:array[, comparer:(a, b) => boolean)]

两个数组的交集部分。

var arr1 = [1, 2, 3, 4, 5];
var arr2 = [1, 2, 3];
// 结果: [1, 2, 3]
var res = arr1.intersect(arr2);

Except

except(arr:array[, comparer:(a, b) => boolean])

两个数组的差异部分。

var arr1 = [1, 2, 3, 4, 5];
var arr2 = [2, 3, 4];
// 结果: [1, 5]
var res = arr1.except(arr2);

Distinct

distinct([comparer:(a, b) => boolean])

返回数组中不重复的元素。

var arr1 = [1, 2, 2, 3, 3, 4, 5, 5];
// 结果: [1, 2, 3, 4, 5]
var res1 = arr.distinct();

var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:1}];
// 结果: [{Name:"A", Val:1}]
var res2 = arr2.distinct(function(a, b){ return a.Val == b.Val });  

Zip

zip(arr: array[, selector:(a, b) => item])

将指定的函数应用于两个数组相同索引的元素(以长度小的数组为准),从而生成结果的序列。

var arr1 = [1, 2, 3, 4, 5];
var arr2 = ["A", "B", "C", "D"];
// 结果: [{Num:1, Letter: "A"},{Num:2, Letter: "B"}, {Num:3, Letter: "C"}, {Num:4, Letter: "D"}]
var res = arr1.zip(arr2, function(a, b){ return {Num:a, Letter:b} });

IndexOf

indexOf(searchElement:any[, fromIndex:number])

返回数组中某个值的第一次出现的索引.

var arr = [1, 2, 3, 2, 5];
// 结果: 1
var index = arr.indexOf(2);
// 结果: 3 起始索引从2开始向后找
var index = arr.indexOf(2, 2);

LastIndexOf

indexOf(searchElement:any[, fromIndex:number])

返回数组中某个值的最后一次出现的索引.

var arr = [1, 2, 3, 4, 5, 3, 4, 5];
// 结果: 5
var index = arr.lastIndexOf(3);
// 结果: 2 起始索引从4开始向前找
var index = arr.lastIndexOf(3,4);

Remove

remove(item: any)

从数组中移除第一次出现的指定对象。

var arr = [1, 2, 3, 4, 5];
// 结果: [1, 3, 4, 5]
arr.remove(2);

RemoveAll

removeAll(selector: (item) => boolean)

移除与指定的条件匹配的所有元素。

var arr = [1, 2, 3, 4, 5];
// 结果: [1, 3, 5]  
arr.removeAll(function(t){ return t % 2 == 0 });

OrderBy

orderBy(selector: item => item[, comparer:(a, b) => boolean])

按照升序排列数组元素.

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;
});

var res3 = arr.orderBy(function(t){ return t.Val }, function(a, b){
    return a - b
});

OrderByDescending

orderByDescending(selector: item => item[, comparer:(a, b) => boolean])

按照降序排列数组元素.

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 });

ThenBy / ThenByDescending

thenBy(selector: item => item[, comparer:(a, b) => boolean])
thenByDescending(selector: item => item[, comparer:(a, b) => boolean])

继续排列数组元素,升序/降序,结合 Orderby 和 OrderByDescending 使用可指定多个排序.

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.Val })
          .thenBy(function(t){ return t.Name });

var res2 = arr.orderBy(function(t){ return t.Val })
          .thenByDescending(function(t){ return t.Name });

var res3 = arr.orderByDescending(function(t){ return t.Val })
          .thenBy(function(t){ return t.Name });

InnerJoin

outer.innerJoin(inner: array, outerKeySelector: item => item , innerKeySelector: item => item, resultSelector: (outer, inner) => item[, comparer:(a, b) => boolean])

内连接,用于显示根据两个数组中的指定属性符合条件的元素.

var arr1 = [{Name:"A", Val:1}, {Name:"B", Val:2}, {Name:"C", Val:3}];

var arr2 = [{Code:"A"}, {Code:"B"}, {Name:"C", Code:"C"}];

var res1 = arr1.innerJoin(arr2,
    function (t) { return t.Name },                                      // arr1 selector
    function (u) { return u.Code },                                      // arr2 selector
    function (t, u) { return { Name: t.Name, Val: t.Val, Code: u.Code } });  // result selector

// using custom comparer
var res2 = arr1.innerJoin(arr2,
    function (t) { return t.Name },                                    // arr1 selector
    function (u) { return u.Code },                                    // arr2 selector
    function (t, u) { return { Name: t.Name, Val: t.Val, Code: u.Code } },  // result selector
    function (a, b) { return a.toUpperCase() == b.toUpperCase() });         // comparer

GroupJoin

outer.groupJoin(inner: array, groupKeyOuterSelector: item => item , groupKeyInnerSelector: item => item, resultSelector: (outer, inner) => item[, comparer:(a, b) => boolean])

基于key的相等将两个数组的元素相关联,并对结果进行分组.

var arr1 = [{Name:"A", Val:1}, {Name:"B", Val:2}, {Name:"C", Val:3}];
var arr2 = [{Code:"A"}, {Code:"A"}, {Code:"B"}, {Code:"B"}, {Code:"C"}];  

var res1 = arr1.groupJoin(arr2,
    function(t){ return t.Name },                     // arr1 selector
    function(u){ return u.Code },                     // arr2 selector
    function(t, u){ return {Item:t, Group:u} }) ;         // result selector  

// using custom comparer  
var res2 = arr1.groupJoin(arr2,
    function(t){ return t.Name },                             // arr1 selector
    function(u){ return u.Code },                             // arr2 selector
    function(t, u){ return {Item:t, Group:u} },                 // result selector
    function(a, b){ return a.toUpperCase() == b.toUpperCase() });     // comparer

GroupBy

groupBy(selector: item => item[, comparer:(a, b) => boolean])

对数组的元素进行分组.

var arr = [{Name:"A", Val:1}, {Name:"B", Val:1}, {Name:"C", Val:2}, {Name:"D", Val:2}];
// 结果: [[{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 });

res.forEach(function(t){
    console.log("Key: " + t.key, "Length: " + t.length);
});
// Key: 1 Length: 2  
// Key: 2 Length: 2

ToDictionary

toDictionary(keySelector: item => item, valueSelector: item => item)

数组转换为对象。

var arr = [1, 2, 3, 4, 5];
// 结果: dic = {Num5: 5, Num4: 4, Num3: 3, Num2: 2, Num1: 1}
var dic = arr.toDictionary(t => "Num" + t, u => u );

Aggregations

Aggregate

aggregate(callback: (previous: any, current: any, index: number, array: array)=> item[, initialValue: any])

在数组上应用累加器函数,等同于Array.reduce。
callback函数接受4个参数:之前值、当前值、索引值以及数组本身。
initialValue参数可选,表示初始值。
若指定initialValue,则当作最初使用的previous值;
如果无initialValue,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。

var arr = [1, 2, 3, 4, 5];
// 结果:15
var sum = arr.aggregate(function(a, b){ return a + b }, 0);

Min

min([selector: item => item])

返回值数组中的最小值。

var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
// 结果:1
var min1 = arr.min();

var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
// 结果:1
var min2 = arr2.min(function(t){ return t.Val });

Max

max([selector: item => item])

返回值数组中的最大值。

var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
// 结果:8
var max1 = arr.max();

var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
// 结果:2
var max2 = arr2.max(function(t){ return t.Val });

Sum

sum([selector: item => item])

计算一个数值数组的和。

var arr1 = [1, 2, 3, 4, 5, 6, 7, 8];
// 结果:36
var sum1 = arr1.sum();

var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:2}];
// 结果:3
var sum2 = arr2.sum(function(t){ return t.Val });

Predicates

Where

where(predicate: item => boolean[, thisObject: any])

基于过滤一数组的值,等同于Array.filter。

var arr = [1, 2, 3, 4, 5];
// 结果:[3, 4, 5]
var res = arr.where(function(t){ return t > 2 }) ;

Any

any(predicate: item => boolean[, thisObject: any])

确定数组中的某个元素是否存在或满足条件,等同于Array.some。

var arr = [1, 2, 3, 4, 5];
// 结果:true
var res1 = arr.any();
// 结果:false
var res2 = arr.any(function(t){ return t > 5 });

All

all(predicate: item => boolean[, thisObject: any])

确定数组中的每个元素是否存在或满足条件,等同于Array.every。

var arr = [1, 2, 3, 4, 5];
// 结果:true
var res = arr.all(function(t){ return t < 6 });

TakeWhile

takeWhile(predicate: item => boolean)

只要指定的条件为true,就返回数组中之前的元素,然后跳过剩余的元素。

var arr = [1, 2, 3, 4, 5, 6, 7, 8];
// 结果:[1, 2, 3]
var res = arr.takeWhile(function(t){ return t % 4 != 0 });

SkipWhile

skipWhile(predicate: item => boolean)

只要指定的条件为true,就会跳过数组中之前的元素,然后返回剩余的元素。

var arr = [1, 2, 3, 4, 5, 6, 7, 8];
// 结果:[ 4, 5, 6, 7, 8]
var res = arr.skipWhile(function(t){ return t % 4 != 0 }) ;

Contains

contains(item: any[, comparer: item => boolean])

确定序列是否包含指定的元素。

var arr1 = [1, 2, 3, 4, 5];
// 结果:true
var res1 = arr.contains(2);

var arr2 = [{Name:"A", Val:1}, {Name:"B", Val:1}];
// 结果:true
var res2 = arr2.contains({Name:"C", Val:1}, function(a, b){ return a.Val == b.Val }) ; 

Iterations

Range

range(start: any, count: any)

返回基于start和end参数的数字数组

// 结果:[1,2,3,4,5]
var range = Array.range(1, 5);

ForEach

range(callback: item => any)[, thisObject: any])

对数组的每个元素执行指定的操作,等同于Array.forEach。

var arr = [1, 2, 3, 4, 5];

arr.forEach(function(t){ if(t % 2 ==0) console.log(t); });

DefaultIfEmpty

defaultIfEmpty(val: any)

如果数组为空,则返回指定的数组元素或单例数组中的指定值。

var arr = [1, 2, 3, 4, 5];
// 结果:[5]
var res = arr.where(function(t){ return t > 5 }).defaultIfEmpty(5);