{"version":3,"file":"intersection.js","names":[],"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 *    intersection(data, other)\n * @example\n *    intersection([1, 2, 3], [2, 3, 5]); // => [2, 3]\n *    intersection([1, 1, 2, 2], [1]); // => [1]\n * @dataFirst\n * @lazy\n * @category Array\n */\nexport function intersection<T, S>(\n  data: readonly T[],\n  other: readonly S[],\n): (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 *    intersection(other)(data)\n * @example\n *    pipe([1, 2, 3], intersection([2, 3, 5])); // => [2, 3]\n *    pipe([1, 1, 2, 2], intersection([1])); // => [1]\n * @dataLast\n * @lazy\n * @category Array\n */\nexport function intersection<S>(\n  other: readonly S[],\n): <T>(data: readonly T[]) => (S & T)[];\n\nexport function intersection(...args: readonly unknown[]): unknown {\n  return purryFromLazy(lazyImplementation, args);\n}\n\nfunction lazyImplementation<T, S>(\n  other: readonly 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":"sGA4CA,SAAgB,EAAa,GAAG,EAAmC,CACjE,OAAO,EAAc,EAAoB,EAAK,CAGhD,SAAS,EACP,EACyB,CACzB,GAAI,EAAM,SAAW,EACnB,OAAO,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,EAG9B,GAML,IAAW,EACb,EAAU,OAAO,EAAM,CAEvB,EAAU,IAAI,EAAO,EAAS,EAAE,CAG3B,CACL,QAAS,GAGT,KAAM,EAEN,KAAM,EAAU,OAAS,EAC1B"}