linqjs记录
- 1.`Enumerable.From(array)`:将普通数组转换为可查询的LINQ.js数组对象。
- 2.`Where(predicate)`:根据指定的条件选择数组中的元素。
- 3.`Select(selector)`:对数组中的每个元素应用指定的转换函数,返回一个新的数组。
- A.......... select和where的区别如下:
- 4.`OrderBy(keySelector)`:按照指定的键选择器对数组进行升序排序。
- 5.`OrderByDescending(keySelector)`:按照指定的键选择器对数组进行降序排序。
- 6.`Reverse()`:反转数组中的元素顺序。
- 7.`Skip(count)`:跳过数组中的前几个元素。
- 8.`Take(count)`:选择数组中的前几个或者前几条元素。
- 9.`groupBy`:指定的键进行分组。
- 10.过滤和筛选数据
- 11.`distinct()` 方法来去重,
- 12.groupBy分组
- 13.将for循环改为linq写法
- 14.去重(.distinct())
- 15.first (返回集合的第一个元素。如果集合中不存在任何元素,则应用程序将抛出异常。如果集合为空,则返回默认值。)
- 16.last (返回集合的最后一个元素。如果集合中不存在任何元素,则应用程序将抛出异常。如果集合为空,LastorDefault返回默认值。)
- 17.single (只有当应用该方法的集合只有一个元素时,该方法才返回一个对象。在singleOrDefault的情况下,只有当它所应用的集合返回单个元素或空集合时,它才返回一个对象。如果集合包含2个或更多元素,则。抛出异常。)
- 18.take(此方法返回指定数量的记录。它通常被用来与orderBy方法一起。)
- 19.contains 类似includes (配合where,条件是contains方法。您可以使用此函数搜索特定的值列表。在本例中,我要查找两个特定的文档号。)
- 20.all (只有当所有元素都满足指定的条件时,all方法才返回true)
- 21.any (any方法只有在没有元素满足谓词中指定的条件时才返回数据。)
- 22.GroupJoin(基于键相等关系将两个序列的元素关联起来,并将结果分组。)
- 23.聚合函数(Aggregation functions)
- 24.MaxBy, MinBy(返回数组中,根据某个属性判断返回某行元素)
- 25.Zip用于连接两个集合
- 26.**forEach**
- 27.多字段排序
- 28.Inner Join 求两个集合的交集(1:1,1:N,...)
- 29.Left Join
- 30.Right join 右外连接
- 31.Full outer join 合并两个表
在LINQ.js中,你可以使用一系列方法来操作数组。以下是一些常见的LINQ.js数组方法:
教程:https://medium.com/swlh/data-manipulation-in-javascript-using-linq-f3759e00aceb
1.Enumerable.From(array)
:将普通数组转换为可查询的LINQ.js数组对象。
2.Where(predicate)
:根据指定的条件选择数组中的元素。
∗ ∗ w h e r e ( p r e d i c a t e : ( e l e m e n t : T , i n d e x : n u m b e r ) = > b o o l e a n ) : I E n u m e r a b l e < T > ; ∗ ∗ **where(predicate: (element: T, index: number) => boolean): IEnumerable<T>;** ∗∗where(predicate:(element:T,index:number)=>boolean):IEnumerable<T>;∗∗
var filteredArray = Enumerable.From(array).Where((x)=> x > 5).ToArray();
3.Select(selector)
:对数组中的每个元素应用指定的转换函数,返回一个新的数组。
- 以下每个元素都乘以2
var transformedArray = Enumerable.From(array).Select((x)=> x * 2).ToArray();
var result = Enumerable.from(array)
.select((user, index) => ({
...user,
id: index + 1
}))
.toArray();
A… select和where的区别如下:
在linq.js中,select和where是用于查询和筛选数据的两个关键字。它们的区别如下:
1. Select:Select用于选择查询结果中的特定字段。它类似于SQL中的SELECT子句。使用Select关键字,你可以指定要从查询结果中返回的字段,并对这些字段进行转换或操作。例如,你可以使用Select来选择一个对象的某个属性,或者对查询结果进行计算或转换。
2. Where:Where用于根据条件筛选出符合条件的数据。它类似于SQL中的WHERE子句。使用Where关键字,你可以指定一个条件表达式,用来过滤查询结果中的数据。只有满足条件的数据才会被包含在结果中。
简而言之,Select用于选择特定字段并对其进行转换或操作,而Where用于筛选符合特定条件的数据。
下面是一个示例,演示如何在linq.js中使用Select和Where:
假设有一个包含学生信息的数组students,每个学生对象都有name和age两个属性。现在我们想选择年龄大于18岁的学生的姓名,可以使用以下代码:
var students = [
{ name: 'Alice', age: 19 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 20 },
{ name: 'David', age: 18 }
];
var result = Enumerable.From(students)
.Where(function(student) {
return student.age > 18;
})
.Select(function(student) {
return student.name;
})
.ToArray();
console.log(result); // 输出: ["Alice", "Charlie"]
在上面的代码中,Where函数用于筛选出年龄大于18岁的学生,而Select函数用于选择学生的姓名。最后,ToArray函数将结果转换为一个数组,方便输出或进一步操作。
希望这个解释对你有帮助!如果有任何问题,请随时提问。
4.OrderBy(keySelector)
:按照指定的键选择器对数组进行升序排序。
var sortedArray = Enumerable.From(array).OrderBy(function(x) {
return x;
}).ToArray();
5.OrderByDescending(keySelector)
:按照指定的键选择器对数组进行降序排序。
var sortedArray = Enumerable.From(array).OrderByDescending(function(x) {
return x;
}).ToArray();
6.Reverse()
:反转数组中的元素顺序。
var reversedArray = Enumerable.From(array).Reverse().ToArray();
7.Skip(count)
:跳过数组中的前几个元素。
var skippedArray = Enumerable.From(array).Skip(2).ToArray();
8.Take(count)
:选择数组中的前几个或者前几条元素。
var takenArray = Enumerable.From(array).Take(3).ToArray();
9.groupBy
:指定的键进行分组。
公式
groupBy<TKey, TElement, TResult, TCompare>(
keySelector: (element: T) => TKey,
elementSelector: (element: T) => TElement,
resultSelector: (key: TKey, element: IEnumerable<TElement>) => TResult, compareSelector: (element: TKey) => TCompare): IEnumerable<TResult>;
let arr = [{ id: 1, name: '' }, { id: 2, name: '测试2' }, { id: 3, name: '测试3' }, { id: 4, name: '测试4' }]
const cdrev = Enumerable.from(arr)
.where(
(c) =>
c.name
)
.groupBy(
(pet) => pet.id,
(pet) => pet,
(key, group) => ({
key: key,
receiveact: group.sum((p) => p.id),
})
)
.toArray();
下面逐步解释代码的作用:
-
创建一个包含对象的数组
arr
:let arr = [{ id: 1, name: '' }, { id: 2, name: '测试2' }, { id: 3, name: '测试3' }, { id: 4, name: '测试4' }]
-
使用
Enumerable.from
方法将数组转换为可查询的对象:const cdrev = Enumerable.from(arr)
-
使用
where
方法进行筛选,只包含name
属性不为空的对象:.where((c) => c.name)
-
使用
groupBy
方法按指定的键进行分组。这里使用id
作为键:.groupBy( (pet) => pet.id, (pet) => pet, (key, group) => ({ key: key, receiveact: group.sum((p) => p.id), }) )
- 第一个参数
(pet) => pet.id
是分组的键,表示按照对象的id
属性进行分组。 - 第二个参数
(pet) => pet
是一个转换函数,它定义了每个分组中的元素应该是什么。 - 第三个参数
(key, group) => ({ key: key, receiveact: group.sum((p) => p.id) })
是一个聚合函数,它定义了如何聚合每个分组的结果。在这里,我们将分组的键作为key
属性,然后计算每个分组中所有元素的id
属性的和作为receiveact
属性。
- 第一个参数
-
最后,使用
toArray
方法将分组的结果转换为数组:.toArray();
总结起来,给定一个包含对象的数组,该代码会筛选出name
属性不为空的对象,并根据id
属性对它们进行分组。然后,对每个分组中的元素进行聚合,生成一个包含key
和receiveact
属性的对象数组。希望这样的解释对你有帮助!
10.过滤和筛选数据
使用 linq.js,你可以使用 Enumerable.from()
方法将数组转换为可查询的对象,然后使用链式调用来过滤和筛选数据。
首先,你需要引入 linq.js 库。然后,你可以使用以下代码来重写你的循环:
// const iftypetwolist = [];
// for (let i = 0; i < list.length; i++) {
// const it = list[i];
// if (it.children && it.children.length == 0 && it.ftype == 2) {
// iftypetwolist.push(it.taskmanagerid);
// iftypetwolist.push(it.taskacterid);
// }
// }
import * as Enumerable from 'linq';
const iftypetwolist = Enumerable.from(list)
.where(it => it.children && it.children.length === 0 && it.ftype === 2)
.selectMany(it => [it.taskmanagerid, it.taskacterid])
.distinct()
.where(it => it !== 0 && it.toString() !== 'null')
.orderBy(it => it)
.toArray();
在上面的代码中,Enumerable.from(list)
将 list
数组转换为可查询的对象。然后,使用 where()
方法来过滤数据,只保留满足条件的元素。接下来,使用 selectMany()
方法来选择并展开每个元素的 taskmanagerid
和 taskacterid
属性,并将它们放入一个新的数组中。然后,使用 distinct()
方法来去重,保留唯一的元素。接着,使用 where()
方法来过滤掉值为 0 或字符串为 ‘null’ 的元素。最后,使用 orderBy()
方法来对数组进行排序,并使用 toArray()
方法将查询结果转换回数组形式。
现在,iftypeonelist
和 iftypetwolist
数组将包含符合条件的元素,并且已经去重、过滤和排序,与你的原始循环的结果相同。
11.distinct()
方法来去重,
条目10有案例
12.groupBy分组
g r o u p B y < T K e y , T E l e m e n t , T R e s u l t , T C o m p a r e > ( k e y S e l e c t o r : ( e l e m e n t : T ) = > T K e y , e l e m e n t S e l e c t o r : ( e l e m e n t : T ) = > T E l e m e n t , r e s u l t S e l e c t o r : ( k e y : T K e y , e l e m e n t : I E n u m e r a b l e < T E l e m e n t > ) = > T R e s u l t , c o m p a r e S e l e c t o r : ( e l e m e n t : T K e y ) = > T C o m p a r e ) : I E n u m e r a b l e < T R e s u l t > ; groupBy<TKey, TElement, TResult, TCompare>( keySelector: (element: T) => TKey, elementSelector: (element: T) => TElement, resultSelector: (key: TKey, element: IEnumerable<TElement>) => TResult, compareSelector: (element: TKey) => TCompare): IEnumerable<TResult>; groupBy<TKey,TElement,TResult,TCompare>(keySelector:(element:T)=>TKey,elementSelector:(element:T)=>TElement,resultSelector:(key:TKey,element:IEnumerable<TElement>)=>TResult,compareSelector:(element:TKey)=>TCompare):IEnumerable<TResult>;
单字段分组
var array = [
{id: 1, name: 'Order 1', product: 'Ford'},
{id: 1, name: 'Order 1', product: 'BMW'},
{id: 2, name: 'Order 2', product: 'Toyota'},
{id: 2, name: 'Order 2', product: 'Skoda'},
{id: 2, name: 'Order 2', product: 'Fiat'}
];
var result = Enumerable.from(array)
.groupBy(
g => g.name,
element => element,
(key, items) => ({key, items: items.toArray()}
)).toArray()
多字段分组
.groupBy(
g => ({ g.name, g.id })),
element => element,
(key, items) => ({key, items: items.toArray()}
)).toArray();
这段代码是使用Vue.js中的groupBy
函数对一个数组进行分组操作。
-
groupBy
函数接受三个参数:一个用于分组的键函数、一个用于选择分组元素的函数和一个用于处理每个分组的函数。 -
第一个参数
(pet) => pet.id
是一个箭头函数,它定义了如何从数组中的每个元素中提取一个键。在这个例子中,我们使用pet.id
作为键来分组。 -
第二个参数
(pet) => pet
是一个箭头函数,它定义了如何选择分组元素。在这个例子中,我们选择了整个pet
对象作为分组元素。 -
第三个参数
(key, group) => ({ key: key, receiveact: group.sum((p) => p.id) })
是一个箭头函数,它定义了如何处理每个分组。在这个例子中,我们创建了一个新的对象,其中包含两个属性:key
和receiveact
。 -
key
属性是分组的键,它的值是第一个参数(pet) => pet.id
提取的键。 -
receiveact
属性是对每个分组中的元素进行求和操作的结果。在这个例子中,我们使用了group.sum((p) => p.id)
来计算每个分组中pet.id
的总和。
总结一下,这段代码的作用是将一个数组按照pet.id
进行分组,并计算每个分组中pet.id
的总和。最终返回一个包含分组键和总和的对象数组。
let arr = [
{ id: 1, name: '测试1' },
{ id: 2, name: '测试2' },
{ id: 3, name: '测试3' },
{ id: 4, name: '测试4' },
];
const cdrev = Enumerable.from(arr)
.where((c) => {
if (c.name) {
return c;
}
})
.groupBy(
(pet) => pet.name,//选择以哪个键分组
(pet) => pet,
(key, group) => ({
key: key,//此时的key等于 pet.name
receiveact: group.sum((p) => p.id),
})
)
.toArray();
//以下代码自动返回对象
.groupBy(
(pet) => pet.billid,
(pet) => pet,
(key, group) => ({
key: key,
fname: '',
billno: '',
pid: 0,
fcount: group.count(),
plantotal: ~~group.sum((p) => p.plantotal),
plantotalaftertax: ~~group.sum((p) => p.plantotalaftertax),
invoicetotal: ~~group.sum((p) => p.invoicetotal),
invoicetotalaftertax: ~~group.sum((p) => p.invoicetotalaftertax),
receiveact: 0,
receiveactaftertax: 0,
percent: 0,
})
)
//第二种请概况,也可以只构建分组
let result = Enumerable.from(arr)
.groupBy((item: any) => item.bigarea)
.select((group) => ({
bigarea: group.key,
questionid: id,
childern: group
.groupBy((item: any) => item.city)
.select((cityGroup: any) => ({
city: cityGroup.key,
childern: cityGroup
.groupBy((it: any) => it.brand)
.select((ftypeGroup: any) => ({
brand: ftypeGroup.key,
plannedNum: ftypeGroup.count(),
childern: ftypeGroup.toArray(),
}))
.toArray(),
}))
.toArray(),
}))
.toArray();
const allQuestionnaireUserList = Enumerable.from(allQuestionnaireUser)
.groupBy((item: any) => item.questionid)
.toObject(
(group) => group.key,
(group) => group.toArray()
);
//分组后设置,属性名
// [
// { ftype: 1, name: '1111' },
// { ftype: 1, name: '2222' },
// { ftype: 2, name: '333333' },
// ];
let groupedByFtype = Enumerable.from(rawData.value)
.groupBy((x: any) => x.ftype)
.select((g: any) => ({
ftype: g.key,
children: g.toArray(),
}))
.toArray();
//原来数组
const originalArray = [
{ id: 1, name: '222' },
{ id: 2, name: '3333' },
{ id: 1, name: 333 },
];
//结果对象
{
1: [{ id: 1, name: '222' },{ id: 1, name: 333 }],
2: [{ id: 2, name: '3333' }],
}
const allQuestionnaireUserList = Enumerable.from(allQuestionnaireUser)
.groupBy((item: any) => item.id)
.toObject(
(group) => group.key,
(group) => group.toArray()
);
13.将for循环改为linq写法
let ftypeArr = [];
for (let i = 0; i < groupedByFtype.length; i++) {
const el = groupedByFtype[i];
let obj = { label: '', value: i + 1 };
obj.label = el.ftype;
ftypeArr.push(obj);
}
let ftypeArr = Enumerable.range(0, groupedByFtype.length)
.select((i) => {
let el = groupedByFtype[i];
return { label: el.ftype, value: i + 1 };
})
.toArray();
使用LINQ.js实现上述代码可以按照以下步骤进行:
1. 首先,确保已经引入了LINQ.js库。
2. 使用LINQ.js的`Enumerable.Range`方法创建一个从0到`groupedByFtype.length - 1`的整数序列。
3. 使用`Enumerable.Select`方法对整数序列进行映射,将每个整数`i`转换为一个包含`label`和`value`属性的对象。
4. 在映射函数中,设置`label`属性为`groupedByFtype[i].ftype`,设置`value`属性为`i + 1`。
5. 使用`Enumerable.ToArray`方法将LINQ查询结果转换为数组。
下面是使用LINQ.js实现的代码:
```javascript
let ftypeArr = Enumerable.Range(0, groupedByFtype.length)
.Select(i => {
let el = groupedByFtype[i];
return { label: el.ftype, value: i + 1 };
})
.ToArray();
```
这样,你就可以使用LINQ.js来实现相同的功能了。
13.0 selectMany:将属性展开为一个扁平的数组(将一个属性对应的值(数组)直接变成循环的数组)
// let arr = [];
// for (let i = 0; i < typePullDownList.value.length; i++) {
// const el = typePullDownList.value[i];
// if (el.value == e) {
// arr = el.children;
// break;
// }
// }
// let cityArr = Enumerable.from(arr)
// .groupBy((x: any) => x.city)
// .select((g: any) => ({
// city: g.key || '未设置城市',
// children: g.toArray(),
// }))
// .select((el, i) => ({
// label: el.city,
// value: i + 1,
// children: el.children,
// }))
// .toArray();
let cityArr = Enumerable.from(typePullDownList.value)
.where((el) => el.value == e)
.selectMany((el) => el.children)
.groupBy((x: any) => x.city)
.select((g: any) => ({
city: g.key || '未设置城市',
children: g.toArray(),
}))
.select((el, i) => ({
label: el.city,
value: i + 1,
children: el.children,
}))
.toArray();
解释: 在这个合并后的代码中,我们首先使用`where`方法筛选出`typePullDownList.value`中`value`属性等于`e`的元素。然后,我们使用`selectMany`方法将这些元素的`children`属性展开为一个扁平的数组。接下来,我们使用`groupBy`将数组按照`city`属性进行分组。然后,我们使用`select`将每个分组转换为一个对象,其中包含`city`和`children`属性。接着,我们使用`select`将每个对象转换为一个新的对象,其中包含`label`、`value`和`children`属性。最后,我们使用`toArray`将结果转换为一个数组。
请注意,我们还添加了一个条件来检查`city`属性是否存在,如果不存在,则将其设置为'未设置城市'。这样可以确保在没有城市属性的情况下,仍然可以正确地生成结果数组。
13.1:常用for循环(firstOrDefault)
let name;
for (let i = 0; i < typePullDownList.value.length; i++) {
const element = typePullDownList.value[i];
if (element.value == typePullDownId.value) {
name = element.label;
break
}
}
使用LINQ.js可以将上述代码转换为以下形式:
```javascript
let name = Enumerable.From(typePullDownList.value)
.Where(element => element.value == typePullDownId.value)
.Select(element => element.label)
.FirstOrDefault();
```
这里的`Enumerable.From`方法将数组`typePullDownList.value`转换为一个可查询的集合。然后使用`Where`方法筛选出`value`属性等于`typePullDownId.value`的元素。接着使用`Select`方法选择`label`属性,并最后使用`FirstOrDefault`方法获取第一个匹配的元素的`label`属性值。
请确保在使用LINQ.js之前先引入该库。
14.去重(.distinct())
itemsmineidarr.value = Enumerable.from(datamod)
.select('tid') // 选择'tid'属性
.distinct() // 去重
.toArray(); // 转换为数组
15.first (返回集合的第一个元素。如果集合中不存在任何元素,则应用程序将抛出异常。如果集合为空,则返回默认值。)
var array = [
{name: 'ondrej', lastname: 'hlouzek', age: 38},
{name: 'jakub', lastname: 'hlouzek', age: 39}
];var result = Enumerable.from(array)
.orderBy(o => o.name)
.first();
16.last (返回集合的最后一个元素。如果集合中不存在任何元素,则应用程序将抛出异常。如果集合为空,LastorDefault返回默认值。)
var array = [
{name: 'ondrej', lastname: 'hlouzek', age: 38},
{name: 'jakub', lastname: 'hlouzek', age: 39}
];var result = Enumerable.from(array)
.orderBy(o => o.name)
.last();
17.single (只有当应用该方法的集合只有一个元素时,该方法才返回一个对象。在singleOrDefault的情况下,只有当它所应用的集合返回单个元素或空集合时,它才返回一个对象。如果集合包含2个或更多元素,则。抛出异常。)
var array = [
{name: 'ondrej', lastname: 'hlouzek', age: 38}
];
var result = Enumerable.from(array)
.single();
18.take(此方法返回指定数量的记录。它通常被用来与orderBy方法一起。)
var array = [
{name: 'Order 1', cost: 15233},
{name: 'Order 2', cost: 33533},
{name: 'Order 3', cost: 23511},
{name: 'Order 4', cost: 11244},
{name: 'Order 5', cost: 44432}
];
var result = Enumerable.from(array)
.orderBy(o => o.cost)
.take(2)
.toArray();
19.contains 类似includes (配合where,条件是contains方法。您可以使用此函数搜索特定的值列表。在本例中,我要查找两个特定的文档号。)
c o n t a i n s ( v a l u e : T ) : b o o l e a n ; contains(value: T): boolean; contains(value:T):boolean;
//查找array中documentNumber在numbers中的数据
var array = [
{documentNumber: '140710', createdDate: '2019-11-01', contract: '', total: 242.64, reference: 'PRIMARK MILAN RCW LAURENCE TAYLOR'},
{documentNumber: '140352', createdDate: '2019-11-02', contract: 'PRI19/00050', total: 22865.90, reference: '***GF WHC***'},
{documentNumber: '140120', createdDate: '2019-11-02', contract: 'PRI19/00052', total: 17732.70, reference: '***GF WHC***'},
{documentNumber: '140117', createdDate: '2019-11-03', contract: 'PRI19/00011', total: 15982.80, reference: '***GF WHC***'},
{documentNumber: '139977', createdDate: '2019-11-04', contract: '', total: 7314.98, reference: '***FIRST FLOOR RCW&PERIMETER***'},
{documentNumber: '139976', createdDate: '2019-11-08', contract: 'PRI19/00028', total: 10147.23, reference: ''},
{documentNumber: '139971', createdDate: '2019-11-13', contract: '', total: 16285.72, reference: '***FIRST FLOOR CD ATRIUMS***'},
{documentNumber: '139968', createdDate: '2019-11-15', contract: '', total: 8111.79, reference: '***FIRST FLOOR B-FRAMES***'},
{documentNumber: '139817', createdDate: '2019-11-18', contract: 'PRI19/00052', total: 5190.59, reference: '***GF RCW&RET***'},
{documentNumber: '139617', createdDate: '2019-11-23', contract: 'PRI19/00052', total: 14378.54, reference: '*****GROUND FLOOR CD*****'}
];
var numbers = ['139976', '139971'];
var result = Enumerable.from(array)
.where(w =>
Enumerable.from(numbers).contains(w.documentNumber))
.toArray();
//结果:[ {documentNumber: '139976', createdDate: '2019-11-08', contract: 'PRI19/00028', total: 10147.23, reference: ''},
//{documentNumber: '139971', createdDate: '2019-11-13', contract: '', total: 16285.72, reference: '***FIRST FLOOR CD //ATRIUMS***'}]
20.all (只有当所有元素都满足指定的条件时,all方法才返回true)
a l l ( p r e d i c a t e : ( e l e m e n t : T ) = > b o o l e a n ) : b o o l e a n ; all(predicate: (element: T) => boolean): boolean; all(predicate:(element:T)=>boolean):boolean;
var array = [1, 2, 3, 4, 5];
var allGreaterThanZero = Enumerable.from(array)
.all(element => element > 0);
console.log(allGreaterThanZero); // 输出 true
21.any (any方法只有在没有元素满足谓词中指定的条件时才返回数据。)
22.GroupJoin(基于键相等关系将两个序列的元素关联起来,并将结果分组。)
g r o u p J o i n < T I n n e r , T K e y , T R e s u l t > ( i n n e r : I E n u m e r a b l e < T I n n e r > , o u t e r K e y S e l e c t o r : ( o u t e r : T ) = > T K e y , i n n e r K e y S e l e c t o r : ( i n n e r : T I n n e r ) = > T K e y , r e s u l t S e l e c t o r : ( o u t e r : T , i n n e r : I E n u m e r a b l e < T I n n e r > ) = > T R e s u l t , c o m p a r e S e l e c t o r ? : ( o b j : T ) = > T K e y ) : I E n u m e r a b l e < T R e s u l t > ; groupJoin<TInner, TKey, TResult>(inner: IEnumerable<TInner>, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: IEnumerable<TInner>) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable<TResult>; groupJoin<TInner,TKey,TResult>(inner:IEnumerable<TInner>,outerKeySelector:(outer:T)=>TKey,innerKeySelector:(inner:TInner)=>TKey,resultSelector:(outer:T,inner:IEnumerable<TInner>)=>TResult,compareSelector?:(obj:T)=>TKey):IEnumerable<TResult>;
var orders = [
{id: 1, name: 'Order 1'}
];
var orderItems = [
{ orderId: 1, product: 'Ford' },
{ orderId: 1, product: 'BMW' }
]
var result = Enumerable.from(orders)
.groupJoin(
Enumerable.from(orderItems),
pk => pk.id,
fk => fk.orderId,
(order, items) => ({...order, items: items.toArray()})
).toArray();
23.聚合函数(Aggregation functions)
min(selector?: (element: T) => number): number;
max(selector?: (element: T) => number): number;
average(selector?: (element: T) => number): number;
count(predicate?: (element: T, index: number) => boolean): number;
sum(selector?: (element: T) => number): number;
可以将以下类型的aggfunc (selector ?: (element: T) => number): number聚合函数应用于IEnumerable<T>集合:
min-返回集合中的最小值
Max -返回集合中的最大值
average-返回集合中的平均值
Count -返回集合中元素的个数
Sum -返回集合中元素的和
var orderItems = [
{ orderId: 1, product: 'Ford', cost: 10000 },
{ orderId: 1, product: 'BMW', cost: 30000 },
{ orderId: 2, product: 'Toyota', cost: 20000 },
{ orderId: 2, product: 'Skoda', cost: 8000 },
{ orderId: 2, product: 'Fiat', cost: 6000 }
]
var result = Enumerable.from(orderItems)
.groupBy(g => g.orderId)
.select(s => ({
orderId: s.key(),
max: s.max(m => m.cost),
min: s.min(m => m.cost),
avg: s.average(m => m.cost),
count: s.count(),
sum: s.sum(s => s.cost)
}))
.toArray();
效果图
24.MaxBy, MinBy(返回数组中,根据某个属性判断返回某行元素)
c o n s t r e s u l t = E n u m e r a b l e . f r o m ( o r d e r s ) . m a x B y ( s = > s . t o t a l ) ; const result = Enumerable.from(orders) .maxBy(s => s.total); constresult=Enumerable.from(orders).maxBy(s=>s.total);
查询查找列(红色列)中的最大值,并返回整个行(黄色行)。
25.Zip用于连接两个集合
zip<U, TResult>(second: IEnumerable<U>, resultSelector: (first: T, second: U, index: number) => TResult): IEnumerable<TResult>
export const orders =
[
{ id: 1, name: 'Order 1', createdDate: '2020.8.1' },
{ id: 2, name: 'Order 2', createdDate: '2020.8.2' },
{ id: 3, name: 'Order 3', createdDate: '2020.8.5' },
{ id: 3, name: 'Order 3', createdDate: '2020.8.5' },
];
export const orderItems =
[
{ row: 1, cost: 20000 },
{ row: 2, cost: 30000 },
{ row: 3, cost: 40000 },
{ row: 4, cost: 50000 },
]
const result = Enumerable.from(orders)
.zip(orderItems, (left, right) => ({ ...left, ...right }))
.toArray();
26.forEach
Enumerable.from(array)
.forEach(f => console.log(`item ${f}`);
27.多字段排序
排序命令如下:
orderBy—第一个按升序排序的命令
orderbydescent—第一个按降序排序的命令
thenBy—下一个按升序排序的命令
thenbydescent—下一个按降序排序的命令
Enumerable.from(array)
.orderByDescending(o => o.lastname)
.thenBy(o => o.name)
.thenByDescending(o => o.age)
28.Inner Join 求两个集合的交集(1:1,1:N,…)
公式
join<TInner, TKey, TResult>(inner: IEnumerable<TInner>, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable<TResult>;
只有当记录存在于两端(集合、表)时,内部连接才返回数据。如果其中一侧或另一侧的记录缺失,则该记录将不会被返回。
.join命令用于实现内部连接。左右集合(表)的连接是使用主键和外键来解决的。只要在左侧和右侧找到匹配,就返回连接的记录。根据图片。左边是主键Id= 1,右边是外键OrderId = 1 pk 1 = fk 1。在这种情况下,返回两行,其中左侧根据右侧的行重复。这是一个类型1:N连接。
结果
29.Left Join
左外连接是返回第一个集合的每个元素的连接,而不管它在第二个集合中是否有任何相关元素。您可以使用LINQ通过对组连接的结果调用DefaultIfEmpty方法来执行左外连接。
在实践中,最常见的情况是连接两个数据源。这是一个连接,只有在主键和外键之间存在连接时,辅助资源才会连接到主资源。主要来源保持不变
const result = Enumerable.from(orders)
.groupJoin(Enumerable.from(orderItems),
pk => pk.id,
fk => fk.orderId,
(left, right) => ({...left, right}))
.selectMany(m => m.right.defaultIfEmpty(),
(left, right) => ({...left, ...right}))
.toArray();
结果
可以封装成函数
export const LeftJoin = (source, inner, pk, fk, result)
=> Enumerable.from(source)
.groupJoin(Enumerable.from(inner),
s => pk(s),
i => fk(i),
(left, right) => ({left, right}))
.selectMany(m => m.right.defaultIfEmpty(),
(prev, right) => result(prev.left, right));
30.Right join 右外连接
右外连接是第二个集合的每个元素所在的连接返回,不管它在第一个元素中是否有任何相关元素收集。方法来执行右外连接在组连接的结果上使用DefaultIfEmpty方法。
右连接与左连接完全相反。这是一个连接,只有当主键和外键之间存在链接时,主资源才会连接到辅助资源。二次源保持不变。
与leftJoin的情况一样,LINQ中没有rightJoin函数,因此我们将使用LINQ自己编写它。
Enumerable.prototype.rightJoin = function(inner, pk, fk, result) {
return RightJoin(this, inner, pk, fk, result);
}
结果如下
const result = Enumerable.from(orders)
.rightJoin(Enumerable.from(orderItems),
pk => pk.id,
fk => fk.orderId,
(left, right) => ({...left, ...right})
).toArray();
31.Full outer join 合并两个表
当左表 (table1) 或右表 (table2) 记录中有匹配项时,FULL OUTER JOIN 关键字将返回所有记录。
它基本上同时执行左连接和右连接。因此,将显示来自左集合和右集合的所有记录。同样,在LINQ中没有调用完全外部连接的等效组件,因此我们编写自己的组件。正如您将看到的,完整的外部连接将是我们已经创建的LeftJoin和RightJoin方法的组合。
export const FullOuterJoin = (source, inner, pk, fk, result) => {
var left = LeftJoin(source, inner, pk, fk, result);
var right = RightJoin(source, inner, pk, fk, result);
return left.unionDistinct(right);
}
我们将用fulllouterjoin方法扩展Enumerable
Enumerable.prototype.fullOuterJoin = function(inner, pk, fk, result) {
return FullOuterJoin(this, inner, pk, fk, result);
}
即使左侧的记录Id = 3在右侧没有相应的记录,右侧的记录Userld = 4在左侧没有相应的记录,它们仍然会在结果集合中。结果如下: