diff --git a/ivette/src/dome/src/renderer/data/compare.ts b/ivette/src/dome/src/renderer/data/compare.ts index 6dcbec1d018875f4d3eceff7f1eafb345d04b700..47c98b71a459a09100cb30fc07aa729fb72e0a0b 100644 --- a/ivette/src/dome/src/renderer/data/compare.ts +++ b/ivette/src/dome/src/renderer/data/compare.ts @@ -222,6 +222,34 @@ export function byAllFields<A>(order: ByAllFields<A>): Order<A> { }; } +export type dict<A> = undefined | null | { [key: string]: A }; + +/** + Compare dictionaries _wrt_ lexicographic order of entries. +*/ +export function dictionary<A>(order: Order<A>): Order<dict<A>> { + return (x: dict<A>, y: dict<A>) => { + if (x === y) return 0; + const dx = x ?? {}; + const dy = y ?? {}; + const phi = option(order); + const fs = Object.getOwnPropertyNames(dx).sort(); + const gs = Object.getOwnPropertyNames(dy).sort(); + const p = fs.length; + const q = gs.length; + for (let i = 0, j = 0; i < p && j < q;) { + let a = undefined, b = undefined; + const f = fs[i]; + const g = gs[j]; + if (f <= g) { a = dx[f]; i++; } + if (g <= f) { b = dy[g]; j++; } + const cmp = phi(a, b); + if (cmp != 0) return cmp; + } + return p - q; + }; +} + /** Pair comparison. */ export function pair<A, B>(ordA: Order<A>, ordB: Order<B>): Order<[A, B]> { return (u, v) => {