Skip to content

Commit 3094eca

Browse files
committed
Adding group by
1 parent 2a74d9a commit 3094eca

File tree

5 files changed

+94
-3
lines changed

5 files changed

+94
-3
lines changed

.gitpod.yml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
tasks:
2+
- init: yarn install
3+
4+
vscode:
5+
extensions:
6+
- [email protected]:9G2nNF/k04qaOhAogmEuMg==
7+

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/berhalak/linq)
2+
13
# linq
24

35
Linq style using generators

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@berhalak/linq",
33
"private": false,
4-
"version": "0.0.9",
4+
"version": "0.0.10",
55
"description": "Typescript linq",
66
"main": "dist/index.js",
77
"types": "dist/index.d.ts",

src/index.spec.ts

+26
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,30 @@ test("ordered", async () => {
8989
expect(from(a).orderByDesc(x => x).first()).toBe(3);
9090
expect(from(a).orderBy(x => 3 - x).first()).toBe(3);
9191
expect(from(a).orderByDesc(x => 3 - x).first()).toBe(1);
92+
});
93+
94+
test("groupBy", async () => {
95+
const a = [{ name : 'a', val: 10}, {name : 'a', val : 20}];
96+
97+
const result = from(a).groupBy(a => a.name).toArray();
98+
99+
expect(result.length).toBe(1);
100+
expect(result[0].count()).toBe(2);
101+
102+
const sum = from(a).groupBy(a => a.name).map(x=> x.sum(y => y.val)).sum(y => y);
103+
104+
expect(sum).toBe(30);
105+
});
106+
107+
test("groupBy", async () => {
108+
const a = [{ name : 'a', val: 10}, {name : 'a', val : 20}];
109+
110+
const result = from(a).groupBy(a => a.name).toArray();
111+
112+
expect(result.length).toBe(1);
113+
expect(result[0].count()).toBe(2);
114+
115+
const sum = from(a).groupBy(a => a.name).map(x=> x.sum(y => y.val)).sum(y => y);
116+
117+
expect(sum).toBe(30);
92118
});

src/index.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ abstract class Enumerable<T> implements Iterable<T> {
2222
return new Mapped(this, selector);
2323
}
2424

25+
groupBy<M>(selector: Selector<T, M>): GroupedEnumerable<T, M> {
26+
return new GroupedEnumerable<T, M>(this, selector);
27+
}
28+
2529
where(filter: Filter<T>): Enumerable<T> {
2630
return new Where(this, filter);
2731
}
@@ -63,10 +67,14 @@ abstract class Enumerable<T> implements Iterable<T> {
6367
return count;
6468
}
6569

66-
sum() {
70+
sum(selector?: Selector<T, number>) {
6771
let sum = 0;
6872
for (let item of this) {
69-
sum += item as any as number;
73+
if (selector) {
74+
sum += selector(item);
75+
} else {
76+
sum += item as any as number;
77+
}
7078
}
7179
return sum;
7280
}
@@ -96,6 +104,54 @@ abstract class Enumerable<T> implements Iterable<T> {
96104
}
97105
}
98106

107+
class Group<V, K> extends Enumerable<V> {
108+
109+
constructor(public key: K, private buffer: V[]) {
110+
super();
111+
}
112+
113+
*[Symbol.iterator](): IterableIterator<V> {
114+
for (let item of this.buffer) {
115+
yield item;
116+
}
117+
}
118+
119+
}
120+
121+
class GroupedEnumerable<V, K> extends Enumerable<Group<V, K>> {
122+
123+
constructor(private list: Enumerable<V>, private selector: Selector<V, K>) {
124+
super();
125+
}
126+
127+
*[Symbol.iterator](): IterableIterator<Group<V, K>> {
128+
// we expect list to be ordered - for perfomence reason
129+
// as this should be as fast as possible
130+
let last: K = null;
131+
let has = false;
132+
let buffer: V[] = [];
133+
for (let item of this.list) {
134+
has = true;
135+
if (last === null) {
136+
last = this.selector(item);
137+
buffer.push(item);
138+
continue;
139+
}
140+
let current = this.selector(item);
141+
if (current != last) {
142+
yield new Group<V, K>(last, buffer);
143+
buffer = [item];
144+
last = current;
145+
continue;
146+
}
147+
buffer.push(item);
148+
}
149+
if (has) {
150+
yield new Group<V, K>(last, buffer);
151+
}
152+
}
153+
}
154+
99155
class Except<T> extends Enumerable<T> {
100156

101157
constructor(private list: Iterable<T>, private other: Iterable<T>) {

0 commit comments

Comments
 (0)