remeda
Version:
A utility library for JavaScript and Typescript.
1 lines • 3.59 kB
Source Map (JSON)
{"version":3,"file":"intersection.cjs","names":["purryFromLazy","lazyEmptyEvaluator","SKIP_ITEM"],"sources":["../src/intersection.ts"],"sourcesContent":["import { purryFromLazy } from \"./internal/purryFromLazy\";\nimport type { LazyEvaluator } from \"./internal/types/LazyEvaluator\";\nimport { SKIP_ITEM, lazyEmptyEvaluator } from \"./internal/utilityEvaluators\";\n\n/**\n * Returns a list of elements that exist in both array. The output maintains the\n * same order as the input. The inputs are treated as multi-sets/bags (multiple\n * copies of items are treated as unique items).\n *\n * @param data - The input items.\n * @param other - The items to compare against.\n * @signature\n * R.intersection(data, other)\n * @example\n * R.intersection([1, 2, 3], [2, 3, 5]); // => [2, 3]\n * R.intersection([1, 1, 2, 2], [1]); // => [1]\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function intersection<T, S>(\n data: ReadonlyArray<T>,\n other: ReadonlyArray<S>,\n): Array<S & T>;\n\n/**\n * Returns a list of elements that exist in both array. The output maintains the\n * same order as the input. The inputs are treated as multi-sets/bags (multiple\n * copies of items are treated as unique items).\n *\n * @param other - The items to compare against.\n * @signature\n * R.intersection(other)(data)\n * @example\n * R.pipe([1, 2, 3], R.intersection([2, 3, 5])); // => [2, 3]\n * R.pipe([1, 1, 2, 2], R.intersection([1])); // => [1]\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function intersection<S>(\n other: ReadonlyArray<S>,\n): <T>(data: ReadonlyArray<T>) => Array<S & T>;\n\nexport function intersection(...args: ReadonlyArray<unknown>): unknown {\n return purryFromLazy(lazyImplementation, args);\n}\n\nfunction lazyImplementation<T, S>(\n other: ReadonlyArray<S>,\n): LazyEvaluator<T, S & T> {\n if (other.length === 0) {\n return lazyEmptyEvaluator;\n }\n\n // We need to build a more efficient data structure that would allow us to\n // keep track of the number of times we've seen a value in the other array.\n const remaining = new Map<S | T, number>();\n for (const value of other) {\n remaining.set(value, (remaining.get(value) ?? 0) + 1);\n }\n\n return (value) => {\n const copies = remaining.get(value);\n\n if (copies === undefined || copies === 0) {\n // The item is either not part of the other array or we've \"used\" enough\n // copies of it so we skip the remaining values.\n return SKIP_ITEM;\n }\n\n // The item is equal to an item in the other array and there are still\n // copies of it to \"account\" for so we return this one and remove it from\n // our ongoing tally.\n if (copies === 1) {\n remaining.delete(value);\n } else {\n remaining.set(value, copies - 1);\n }\n\n return {\n hasNext: true,\n // We can safely cast here because if value was in the `remaining` map, it\n // has to be of type S (that's just how we built it).\n next: value as S & T,\n // We can stop the iteration if the remaining map is empty.\n done: remaining.size === 0,\n };\n };\n}\n"],"mappings":"8FA4CA,SAAgB,EAAa,GAAG,EAAuC,CACrE,OAAOA,EAAAA,EAAc,EAAoB,EAAK,CAGhD,SAAS,EACP,EACyB,CACzB,GAAI,EAAM,SAAW,EACnB,OAAOC,EAAAA,EAKT,IAAM,EAAY,IAAI,IACtB,IAAK,IAAM,KAAS,EAClB,EAAU,IAAI,GAAQ,EAAU,IAAI,EAAM,EAAI,GAAK,EAAE,CAGvD,MAAQ,IAAU,CAChB,IAAM,EAAS,EAAU,IAAI,EAAM,CAiBnC,OAfI,IAAW,IAAA,IAAa,IAAW,EAG9BC,EAAAA,GAML,IAAW,EACb,EAAU,OAAO,EAAM,CAEvB,EAAU,IAAI,EAAO,EAAS,EAAE,CAG3B,CACL,QAAS,GAGT,KAAM,EAEN,KAAM,EAAU,OAAS,EAC1B"}