Skip to content

Commit 48d32af

Browse files
committed
feat(expr): Make intersects() return the intersection when non-empty
1 parent 4db5044 commit 48d32af

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

src/schema/expressionLanguage.test.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,26 @@ Deno.test('test expression functions', async (t) => {
1616
})
1717
await t.step('intersects function', () => {
1818
const intersects = expressionFunctions.intersects
19-
assert(intersects([1, 2, 3], [2, 3, 4]) === true)
20-
assert(intersects([1, 2, 3], [4, 5, 6]) === false)
21-
assert(intersects(['abc', 'def'], ['def']) === true)
22-
assert(intersects(['abc', 'def'], ['ghi']) === false)
19+
const truthy = (a: any): boolean => !!a
20+
const falsey = (a: any): boolean => !a
21+
const equal = expressionFunctions.allequal
22+
assert(truthy(intersects([1, 2, 3], [2, 3, 4])))
23+
assert(falsey(intersects([1, 2, 3], [4, 5, 6])))
24+
assert(truthy(intersects(['abc', 'def'], ['def'])))
25+
assert(falsey(intersects(['abc', 'def'], ['ghi'])))
26+
// Just checking values, I'm not concerned about types here
27+
// @ts-expect-error
28+
assert(equal(intersects([1, 2, 3], [2, 3, 4]), [2, 3]))
29+
// @ts-expect-error
30+
assert(equal(intersects(['abc', 'def'], ['def']), ['def']))
2331

2432
// Promote scalars to arrays
2533
// @ts-ignore
26-
assert(intersects('abc', ['abc', 'def']) === true)
34+
assert(truthy(intersects('abc', ['abc', 'def'])))
2735
// @ts-ignore
28-
assert(intersects('abc', ['a', 'b', 'c']) === false)
36+
assert(falsey(intersects('abc', ['a', 'b', 'c'])))
37+
// @ts-expect-error
38+
assert(equal(intersects('abc', ['abc', 'def']), ['abc']))
2939
})
3040
await t.step('match function', () => {
3141
const match = expressionFunctions.match

src/schema/expressionLanguage.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,30 @@ export const expressionFunctions = {
4040
const index = list.indexOf(item)
4141
return index != -1 ? index : null
4242
},
43-
intersects: <T>(a: T[], b: T[]): boolean => {
43+
intersects: <T>(a: T[], b: T[]): T[] | null => {
44+
// Tolerate single values
4445
if (!Array.isArray(a)) {
4546
a = [a]
4647
}
4748
if (!Array.isArray(b)) {
4849
b = [b]
4950
}
50-
return a.some((x) => b.includes(x))
51+
// Construct a set from the smaller list
52+
if (a.length < b.length) {
53+
const tmp = a
54+
a = b
55+
b = tmp
56+
}
57+
if (b.length === 0) {
58+
return null
59+
}
60+
61+
const bSet = new Set(b)
62+
const intersection = a.filter((x) => bSet.has(x))
63+
if (intersection.length === 0) {
64+
return null
65+
}
66+
return intersection
5167
},
5268
match: (target: string, regex: string): boolean => {
5369
const re = RegExp(regex)

0 commit comments

Comments
 (0)