Skip to content

Commit 3a66a21

Browse files
authored
Merge pull request #150 from effigies/feat/intersects
feat(expr): Make intersects() return the intersection when non-empty
2 parents 161b86c + 2fc981c commit 3a66a21

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

src/schema/expressionLanguage.test.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,27 @@ 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)
19+
const equal = expressionFunctions.allequal
20+
21+
const truthy = (a: any): boolean => !!a
22+
23+
assert(truthy(intersects([1, 2, 3], [2, 3, 4])))
2024
assert(intersects([1, 2, 3], [4, 5, 6]) === false)
21-
assert(intersects(['abc', 'def'], ['def']) === true)
25+
assert(truthy(intersects(['abc', 'def'], ['def'])))
2226
assert(intersects(['abc', 'def'], ['ghi']) === false)
27+
// Just checking values, I'm not concerned about types here
28+
// @ts-expect-error
29+
assert(equal(intersects([1, 2, 3], [2, 3, 4]), [2, 3]))
30+
// @ts-expect-error
31+
assert(equal(intersects(['abc', 'def'], ['def']), ['def']))
2332

2433
// Promote scalars to arrays
2534
// @ts-ignore
26-
assert(intersects('abc', ['abc', 'def']) === true)
35+
assert(truthy(intersects('abc', ['abc', 'def'])))
2736
// @ts-ignore
2837
assert(intersects('abc', ['a', 'b', 'c']) === false)
38+
// @ts-expect-error
39+
assert(equal(intersects('abc', ['abc', 'def']), ['abc']))
2940
})
3041
await t.step('match function', () => {
3142
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[] | boolean => {
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 false
59+
}
60+
61+
const bSet = new Set(b)
62+
const intersection = a.filter((x) => bSet.has(x))
63+
if (intersection.length === 0) {
64+
return false
65+
}
66+
return intersection
5167
},
5268
match: (target: string, regex: string): boolean => {
5369
const re = RegExp(regex)

src/tests/schema-expression-language.test.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const equal = <T>(a: T, b: T): boolean => {
1919
Deno.test('validate schema expression tests', async (t) => {
2020
const results: string[][] = []
2121
const header = ['expression', 'desired', 'actual', 'result'].map((x) => colors.magenta(x))
22+
const xfails = ['intersects([1], [1, 2])']
2223
for (const test of schema.meta.expression_tests) {
2324
await t.step(`${test.expression} evals to ${test.result}`, () => {
2425
const context = { file: { parent: null }, dataset: { tree: null } } as unknown as BIDSContext
@@ -33,6 +34,13 @@ Deno.test('validate schema expression tests', async (t) => {
3334
pretty_null(actual_result),
3435
colors.green('pass'),
3536
])
37+
} else if (xfails.includes(test.expression)) {
38+
results.push([
39+
colors.cyan(test.expression),
40+
pretty_null(test.result),
41+
pretty_null(actual_result),
42+
colors.yellow('xfail'),
43+
])
3644
} else {
3745
results.push([
3846
colors.cyan(test.expression),
@@ -41,7 +49,10 @@ Deno.test('validate schema expression tests', async (t) => {
4149
colors.red('fail'),
4250
])
4351
}
44-
assertEquals(actual_result, test.result)
52+
// Don't fail on xfail
53+
if (!xfails.includes(test.expression)) {
54+
assertEquals(actual_result, test.result)
55+
}
4556
})
4657
}
4758
results.sort((a, b) => {

0 commit comments

Comments
 (0)