import { EqualityComparer, IEnumerable, IEnumerableFactory } from '../../types'; export function applyRightJoinHeterogeneous( factory: IEnumerableFactory, first: Iterable, second: Iterable, firstKeySelector: (item: TFirst) => TKey, secondKeySelector: (item: TSecond) => TKey, secondSelector: (item: TSecond) => TResult, bothSelector: (a: TFirst, b: TSecond) => TResult, equalityComparer?: EqualityComparer ): IEnumerable { function* generator(): Generator { if (equalityComparer) { for (const secondItem of second) { const secondKey = secondKeySelector(secondItem); let matched = false; for (const firstItem of first) { if (equalityComparer(secondKey, firstKeySelector(firstItem))) { matched = true; yield bothSelector(firstItem, secondItem); } } if (!matched) { yield secondSelector(secondItem); } } } else { const firstKeyMap = new Map(); for (const firstItem of first) { const firstKey = firstKeySelector(firstItem); const currentMatches = firstKeyMap.get(firstKey); if (currentMatches !== undefined) { currentMatches.push(firstItem); } else { firstKeyMap.set(firstKey, [firstItem]); } } for (const secondItem of second) { const secondKey = secondKeySelector(secondItem); const firstMatches = firstKeyMap.get(secondKey); if (firstMatches !== undefined) { for (let i = 0; i < firstMatches.length; i++) { yield bothSelector(firstMatches[i], secondItem); } } else { yield secondSelector(secondItem); } } } } return factory.createBasicEnumerable(generator); } export function applyRightJoinHomogeneous( factory: IEnumerableFactory, first: Iterable, second: Iterable, keySelector: (item: TFirst) => TKey, secondSelector: (item: TFirst) => TResult, bothSelector: (a: TFirst, b: TFirst) => TResult, equalityComparer?: EqualityComparer ): IEnumerable { function* generator(): Generator { if (equalityComparer) { for (const secondItem of second) { const secondKey = keySelector(secondItem); let matched = false; for (const firstItem of first) { if (equalityComparer(secondKey, keySelector(firstItem))) { matched = true; yield bothSelector(firstItem, secondItem); } } if (!matched) { yield secondSelector(secondItem); } } } else { const firstKeyMap = new Map(); for (const firstItem of first) { const firstKey = keySelector(firstItem); const currentMatches = firstKeyMap.get(firstKey); if (currentMatches !== undefined) { currentMatches.push(firstItem); } else { firstKeyMap.set(firstKey, [firstItem]); } } for (const secondItem of second) { const secondKey = keySelector(secondItem); const firstMatches = firstKeyMap.get(secondKey); if (firstMatches !== undefined) { for (let i = 0; i < firstMatches.length; i++) { yield bothSelector(firstMatches[i], secondItem); } } else { yield secondSelector(secondItem); } } } } return factory.createBasicEnumerable(generator); }