Lab
Strategy
type SearchResult = { id: string; score: number; ageDays: number };
// A policy compares two results. Negative: a first. Zero: tied. Positive: b first.
type RankingPolicy = (a: SearchResult, b: SearchResult) => number;
function byRelevance(a: SearchResult, b: SearchResult): number {
return b.score - a.score;
}
function byRecent(a: SearchResult, b: SearchResult): number {
return a.ageDays - b.ageDays;
}
// The shared workflow: copy, ask the policy, and settle its ties by ID.
function rankResults(items: SearchResult[], policy: RankingPolicy): SearchResult[] {
const ranked = [...items];
function compare(a: SearchResult, b: SearchResult): number {
const order = policy(a, b);
const tied = order === 0;
if (!tied) return order;
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
}
ranked.sort(compare);
return ranked;
}
const results: SearchResult[] = [
{ id: 'cache', score: 90, ageDays: 30 },
{ id: 'api', score: 90, ageDays: 7 },
{ id: 'release', score: 65, ageDays: 1 },
];
const ids = (items: SearchResult[]) => items.map((item) => item.id).join(', ');
const relevance = rankResults(results, byRelevance);
const recent = rankResults(results, byRecent);
console.log(`relevance: ${ids(relevance)}`);
console.log(`recent: ${ids(recent)}`);
console.log(`as returned: ${ids(results)}`);
TODO
Visual to come