expect(result[0].score).toBe(0.85);
});
- test("different type contained removed", () => {
+ test("different type overlapping higher score wins", () => {
const entities = [
{ start: 0, end: 10, score: 0.7, entity_type: "PHONE_NUMBER" },
{ start: 2, end: 8, score: 0.9, entity_type: "US_SSN" },
];
const result = resolveConflicts(entities);
expect(result).toHaveLength(1);
- expect(result[0].entity_type).toBe("PHONE_NUMBER");
+ expect(result[0].entity_type).toBe("US_SSN");
});
test("same indices different types higher score wins", () => {
expect(result[0].entity_type).toBe("EMAIL_ADDRESS");
});
+ test("partial overlap different types higher score wins", () => {
+ const entities = [
+ { start: 0, end: 10, score: 0.7, entity_type: "PHONE_NUMBER" },
+ { start: 5, end: 15, score: 0.9, entity_type: "EMAIL_ADDRESS" },
+ ];
+ const result = resolveConflicts(entities);
+ expect(result).toHaveLength(1);
+ expect(result[0].entity_type).toBe("EMAIL_ADDRESS");
+ });
+
test("Eric vs Eric's merged correctly", () => {
const entities = [
{ start: 6, end: 10, score: 0.85, entity_type: "PERSON" },
if (entities.length <= 1) return [...entities];
const sorted = [...entities].sort((a, b) => {
- if (a.start !== b.start) return a.start - b.start;
- if (a.end !== b.end) return a.end - b.end;
- return b.score - a.score;
+ if (a.score !== b.score) return b.score - a.score;
+ const aLen = a.end - a.start;
+ const bLen = b.end - b.start;
+ if (aLen !== bLen) return bLen - aLen;
+ return a.start - b.start;
});
const result: T[] = [];
for (const entity of sorted) {
- const hasConflict = result.some((kept) => {
- if (entity.start === kept.start && entity.end === kept.end) {
- return true;
- }
- return isContainedIn(entity, kept);
- });
+ const hasConflict = result.some((kept) => overlaps(entity, kept));
if (!hasConflict) {
result.push(entity);