mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
feat(collections/unstable): support Iterable
argument in intersect()
(#6036)
This commit is contained in:
parent
065296ca5a
commit
a6a9b86fec
@ -48,6 +48,7 @@
|
|||||||
"./union": "./union.ts",
|
"./union": "./union.ts",
|
||||||
"./unstable-chunk": "./unstable_chunk.ts",
|
"./unstable-chunk": "./unstable_chunk.ts",
|
||||||
"./unstable-drop-last-while": "./unstable_drop_last_while.ts",
|
"./unstable-drop-last-while": "./unstable_drop_last_while.ts",
|
||||||
|
"./unstable-intersect": "./unstable_intersect.ts",
|
||||||
"./unstable-sample": "./unstable_sample.ts",
|
"./unstable-sample": "./unstable_sample.ts",
|
||||||
"./unstable-sort-by": "./unstable_sort_by.ts",
|
"./unstable-sort-by": "./unstable_sort_by.ts",
|
||||||
"./unstable-take-while": "./unstable_take_while.ts",
|
"./unstable-take-while": "./unstable_take_while.ts",
|
||||||
|
38
collections/unstable_intersect.ts
Normal file
38
collections/unstable_intersect.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// This module is browser compatible.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all distinct elements that appear at least once in each of the given
|
||||||
|
* iterables.
|
||||||
|
*
|
||||||
|
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
||||||
|
*
|
||||||
|
* @typeParam T The type of the elements in the input iterables.
|
||||||
|
*
|
||||||
|
* @param iterables The iterables to intersect.
|
||||||
|
*
|
||||||
|
* @returns An array of distinct elements that appear at least once in each of
|
||||||
|
* the given iterables.
|
||||||
|
*
|
||||||
|
* @example Basic usage
|
||||||
|
* ```ts
|
||||||
|
* import { intersect } from "@std/collections/unstable-intersect";
|
||||||
|
* import { assertEquals } from "@std/assert";
|
||||||
|
*
|
||||||
|
* const lisaInterests = ["Cooking", "Music", "Hiking"];
|
||||||
|
* const kimInterests = ["Music", "Tennis", "Cooking"];
|
||||||
|
* const commonInterests = intersect(lisaInterests, kimInterests);
|
||||||
|
*
|
||||||
|
* assertEquals(commonInterests, ["Cooking", "Music"]);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function intersect<T>(...iterables: Iterable<T>[]): T[] {
|
||||||
|
const [iterable, ...otherIterables] = iterables;
|
||||||
|
let set = new Set(iterable);
|
||||||
|
if (set.size === 0) return [];
|
||||||
|
for (const iterable of otherIterables) {
|
||||||
|
set = set.intersection(new Set(iterable));
|
||||||
|
if (set.size === 0) return [];
|
||||||
|
}
|
||||||
|
return [...set];
|
||||||
|
}
|
177
collections/unstable_intersect_test.ts
Normal file
177
collections/unstable_intersect_test.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { assert, assertEquals } from "@std/assert";
|
||||||
|
import { intersect } from "./unstable_intersect.ts";
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles no mutation", () => {
|
||||||
|
const arrayA = [1, 2, 3];
|
||||||
|
const arrayB = [3, 4, 5];
|
||||||
|
intersect(arrayA, arrayB);
|
||||||
|
assertEquals(arrayA, [1, 2, 3]);
|
||||||
|
assertEquals(arrayB, [3, 4, 5]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles empty input", () => {
|
||||||
|
const actual = intersect();
|
||||||
|
assertEquals(actual, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles empty arrays", () => {
|
||||||
|
const actual = intersect([], []);
|
||||||
|
assertEquals(actual, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles one side empty", () => {
|
||||||
|
const firstEmpty = intersect([], [1, 2, 3]);
|
||||||
|
const secondEmpty = intersect([1, 2, 3], []);
|
||||||
|
assertEquals(firstEmpty, []);
|
||||||
|
assertEquals(secondEmpty, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles empty result", () => {
|
||||||
|
const actual = intersect(["a", "b", "c"], ["d", "e", "f"]);
|
||||||
|
assertEquals(actual, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles one or more items in intersection", () => {
|
||||||
|
const one = intersect(["a", "b"], ["b", "c"]);
|
||||||
|
const orMore = intersect(["a", "b", "c", "d"], ["c", "d", "e", "f"]);
|
||||||
|
assertEquals(one, ["b"]);
|
||||||
|
assertEquals(orMore, ["c", "d"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles duplicates", () => {
|
||||||
|
const duplicates = intersect(["a", "b", "c", "b"], ["b", "c"]);
|
||||||
|
const moreDuplicates = intersect(["a", "b"], ["b", "b", "c", "c"]);
|
||||||
|
assertEquals(duplicates, ["b", "c"]);
|
||||||
|
assertEquals(moreDuplicates, ["b"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles more than two inputs", () => {
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
["a", "b"],
|
||||||
|
["b", "c"],
|
||||||
|
["s", "b"],
|
||||||
|
["b", "b"],
|
||||||
|
),
|
||||||
|
["b"],
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
[1],
|
||||||
|
[1],
|
||||||
|
[2],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
[true, false],
|
||||||
|
[true, false],
|
||||||
|
[true],
|
||||||
|
),
|
||||||
|
[true],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles objects", () => {
|
||||||
|
assertEquals(
|
||||||
|
intersect<Record<string, string>>(
|
||||||
|
[{ foo: "bar" }, { bar: "baz" }],
|
||||||
|
[{ fruit: "banana" }],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const obj = { bar: "baz" };
|
||||||
|
assertEquals(
|
||||||
|
intersect<Record<string, string>>(
|
||||||
|
[{ foo: "bar" }, obj],
|
||||||
|
[obj],
|
||||||
|
),
|
||||||
|
[obj],
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
intersect<Record<string, string>>(
|
||||||
|
[{ foo: "bar" }, { bar: "baz" }],
|
||||||
|
[{ bar: "banana" }],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles functions", () => {
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
[() => {}, () => null],
|
||||||
|
[() => NaN],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const emptyObjectFunction = () => {};
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
[emptyObjectFunction, () => null],
|
||||||
|
[emptyObjectFunction],
|
||||||
|
),
|
||||||
|
[emptyObjectFunction],
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
intersect(
|
||||||
|
[(a: number, b: number) => a + b, () => null],
|
||||||
|
[(a: number, b: number) => a - b],
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If you are using sets using {@linkcode Set.prototype.intersection} directly is more efficient.
|
||||||
|
Deno.test("(unstable) intersect() handles sets", () => {
|
||||||
|
const a = new Set([1, 2, 3, 4]);
|
||||||
|
const b = new Set([2, 3]);
|
||||||
|
assertEquals(intersect(a, b), [2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles iterables of different types", () => {
|
||||||
|
const arr = [1, 2, 3, 4, 5, 6];
|
||||||
|
const set = new Set([1, 2, 3, 4, 5]);
|
||||||
|
function* gen() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
yield 3;
|
||||||
|
}
|
||||||
|
const iterable = {
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
yield 3;
|
||||||
|
yield 6;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
assertEquals(intersect(arr, set, gen(), iterable), [3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles iterables with no mutation", () => {
|
||||||
|
const a = [1, 2, 3, 4];
|
||||||
|
const b = new Set([2, 3]);
|
||||||
|
intersect(a, b);
|
||||||
|
assertEquals(a, [1, 2, 3, 4]);
|
||||||
|
assert(b.has(2));
|
||||||
|
assert(b.has(3));
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("(unstable) intersect() handles generators", () => {
|
||||||
|
function* gen() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
yield 3;
|
||||||
|
yield 4;
|
||||||
|
}
|
||||||
|
function* gen2() {
|
||||||
|
yield 2;
|
||||||
|
yield 3;
|
||||||
|
}
|
||||||
|
assertEquals(intersect(gen(), gen2()), [2, 3]);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user