linqjs记录
在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.namereceiveact: 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在左侧没有相应的记录,它们仍然会在结果集合中。结果如下: