From 6321531cdaa259520c9a6e4f681f668bf0dd7b7e Mon Sep 17 00:00:00 2001 From: miquik Date: Thu, 24 Mar 2022 09:15:38 +0100 Subject: [PATCH 1/3] leftJoin first commit --- linq.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/linq.js b/linq.js index c29ecf6..29091b9 100644 --- a/linq.js +++ b/linq.js @@ -1063,6 +1063,54 @@ Enumerable.prototype.join = function (inner, outerKeySelector, innerKeySelector, }); }; +// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector) +// Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) +Enumerable.prototype.leftJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) { + outerKeySelector = Utils.createLambda(outerKeySelector); + innerKeySelector = Utils.createLambda(innerKeySelector); + resultSelector = Utils.createLambda(resultSelector); + compareSelector = Utils.createLambda(compareSelector); + var source = this; + + return new Enumerable(function () { + var outerEnumerator; + var lookup; + var innerElements = null; + var innerCount = 0; + + return new IEnumerator( + function () { + outerEnumerator = source.getEnumerator(); + lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, compareSelector); + }, + function () { + while (true) { + if (innerElements != null) { + let innerElement = innerElements[innerCount++]; + if (innerElement !== undefined) { + return this.yieldReturn(resultSelector(outerEnumerator.current(), innerElement)); + } + + innerElement = null; + innerCount = 0; + } + + if (outerEnumerator.moveNext()) { + const key = outerKeySelector(outerEnumerator.current()); + innerElements = lookup.get(key).toArray(); + // execute once if innerElements is NULL + if (innerElements == null) { + return this.yieldReturn(resultSelector(outerEnumerator.current(), null)); + } + } else { + return false; + } + } + }, + function () { Utils.dispose(outerEnumerator); }); + }); +}; + // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector) // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) Enumerable.prototype.groupJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, compareSelector) { From 80769627c687ebb435486351b1e3120374ec2096 Mon Sep 17 00:00:00 2001 From: miquik Date: Thu, 24 Mar 2022 09:18:29 +0100 Subject: [PATCH 2/3] leftJoin second commit --- linq.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linq.d.ts b/linq.d.ts index 18eb949..a9e7d4e 100644 --- a/linq.d.ts +++ b/linq.d.ts @@ -68,6 +68,9 @@ declare namespace Enumerable { join(inner: IEnumerable, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; join(inner: { length: number;[x: number]: TInner; }, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; join(inner: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; + leftJoin(inner: IEnumerable, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; + leftJoin(inner: { length: number;[x: number]: TInner; }, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; + leftJoin(inner: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; groupJoin(inner: IEnumerable, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: IEnumerable) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; groupJoin(inner: { length: number;[x: number]: TInner; }, outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: IEnumerable) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; groupJoin(inner: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: IEnumerable) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable; From 62c8c32a60820f1255ad3b9484faa820ea1911b6 Mon Sep 17 00:00:00 2001 From: miquik Date: Wed, 30 Mar 2022 09:17:56 +0200 Subject: [PATCH 3/3] correct some error --- LINQJS.code-workspace | 8 ++++++++ linq.js | 2 +- test/join.js | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 LINQJS.code-workspace diff --git a/LINQJS.code-workspace b/LINQJS.code-workspace new file mode 100644 index 0000000..bab1b7f --- /dev/null +++ b/LINQJS.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": ".." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/linq.js b/linq.js index 29091b9..0be1f96 100644 --- a/linq.js +++ b/linq.js @@ -1099,7 +1099,7 @@ Enumerable.prototype.leftJoin = function (inner, outerKeySelector, innerKeySelec const key = outerKeySelector(outerEnumerator.current()); innerElements = lookup.get(key).toArray(); // execute once if innerElements is NULL - if (innerElements == null) { + if (innerElements == null || innerElements.length == 0) { return this.yieldReturn(resultSelector(outerEnumerator.current(), null)); } } else { diff --git a/test/join.js b/test/join.js index 48a3dc5..3070f35 100755 --- a/test/join.js +++ b/test/join.js @@ -85,3 +85,27 @@ test("groupJoin", function () { outer: 6, collection: [2, 4, 6, 6]}]; deepEqual(actual, expected); }); + +test("leftJoin", function () +{ + var math = { yamada: 100, tanaka: 80, yoshida: 94 }; + var english = { yamada: 73, tanaka: 99 }; + let actual = Enumerable.from(math) + .leftJoin(english, "outer=>outer.key", "inner=>inner.key", + (o,i) => ({Name:o.key,Math:o.value,English:i == null ? null : i.value})) + .toArray(); + let expected = [{ Name: "yamada", Math: 100, English: 73 }, + { Name: "tanaka", Math: 80, English: 99 }, + { Name: "yoshida", Math: 94, English: null}]; + deepEqual(actual, expected); + + actual = Enumerable.from(math) + .leftJoin(english, "outer=>outer", "inner=>inner", + (o,i) => ({Name:o.key,Math:o.value,English:i == null ? null : i.value}), + "$.key") + .toArray(); + expected = [{ Name: "yamada", Math: 100, English: 73 }, + { Name: "tanaka", Math: 80, English: 99 }, + { Name: "yoshida", Math: 94, English: null}]; + deepEqual(actual, expected); +}); \ No newline at end of file