Skip to content

Commit

Permalink
Merge pull request #93 from miquik/master
Browse files Browse the repository at this point in the history
Left Join implementation
  • Loading branch information
mihaifm committed Mar 30, 2022
2 parents 0b5c308 + 62c8c32 commit 06b7c1b
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
8 changes: 8 additions & 0 deletions LINQJS.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"folders": [
{
"path": ".."
}
],
"settings": {}
}
3 changes: 3 additions & 0 deletions linq.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ declare namespace Enumerable {
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<TInner, TKey, TResult>(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<TResult>;
join<TInner, TKey, TResult>(inner: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: TInner) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable<TResult>;
leftJoin<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>;
leftJoin<TInner, TKey, TResult>(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<TResult>;
leftJoin<TInner, TKey, TResult>(inner: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: 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>;
groupJoin<TInner, TKey, TResult>(inner: { length: number;[x: number]: 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: TInner[], outerKeySelector: (outer: T) => TKey, innerKeySelector: (inner: TInner) => TKey, resultSelector: (outer: T, inner: IEnumerable<TInner>) => TResult, compareSelector?: (obj: T) => TKey): IEnumerable<TResult>;
Expand Down
48 changes: 48 additions & 0 deletions linq.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 || innerElements.length == 0) {
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) {
Expand Down
24 changes: 24 additions & 0 deletions test/join.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

0 comments on commit 06b7c1b

Please sign in to comment.