UNPKG

assertthat

Version:
161 lines (160 loc) 6.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.compareArrays = void 0; const compare_1 = require("../typeAware/compare"); const typedescriptor_1 = require("typedescriptor"); const maximumDiffTableSize_1 = require("../../constants/maximumDiffTableSize"); const simplifyDiff_1 = require("../../diffs/forArrays/simplifyDiff"); const size_1 = require("../../size/typeAware/size"); const ArrayDiff_1 = require("../../diffs/forArrays/ArrayDiff"); const EqualDiff_1 = require("../../diffs/EqualDiff"); const compareArraysLinearly = function (actual, expected) { const diff = (0, ArrayDiff_1.arrayDiff)({ segments: [], cost: 0 }); for (let i = 0; i < Math.max(actual.length, expected.length); i++) { const actualItem = actual[i]; const expectedItem = expected[i]; if ((0, typedescriptor_1.isUndefined)(actualItem)) { diff.segments.push({ omission: [expectedItem], cost: (0, size_1.size)(expectedItem) }); continue; } if ((0, typedescriptor_1.isUndefined)(expectedItem)) { diff.segments.push({ addition: [actualItem], cost: (0, size_1.size)(actualItem) }); continue; } const subDiff = (0, compare_1.compare)(actualItem, expectedItem); if ((0, EqualDiff_1.isEqualDiff)(subDiff)) { diff.segments.push({ equal: [actualItem], cost: 0 }); } else { diff.segments.push({ change: [subDiff], cost: subDiff.cost }); } } if (diff.cost === 0) { return (0, EqualDiff_1.equalDiff)({ value: actual }); } return (0, simplifyDiff_1.simplifyDiff)(diff); }; const compareArraysBestMatch = function (actual, expected) { const results = new Map(); results.set('-1|-1', (0, ArrayDiff_1.arrayDiff)({ segments: [], cost: 0 })); for (let indexActual = 0; indexActual < actual.length; indexActual++) { const segment = { addition: [], cost: 0 }; for (let index = 0; index <= indexActual; index++) { segment.addition.push(actual[index]); segment.cost += (0, size_1.size)(actual[index]); } results.set(`${indexActual}|-1`, (0, ArrayDiff_1.arrayDiff)({ segments: [segment], cost: segment.cost })); } for (let indexExpected = 0; indexExpected < expected.length; indexExpected++) { const segment = { omission: [], cost: 0 }; for (let index = 0; index <= indexExpected; index++) { segment.omission.push(expected[index]); segment.cost += (0, size_1.size)(expected[index]); } results.set(`-1|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({ segments: [segment], cost: segment.cost })); } for (const [indexActual, elementActual] of actual.entries()) { for (const [indexExpected, elementExpected] of expected.entries()) { const maybeEqualPreviousDiff = results.get(`${indexActual - 1}|${indexExpected - 1}`); const maybeEqualCurrentDiff = (0, compare_1.compare)(elementActual, elementExpected); const maybeEqualCost = maybeEqualPreviousDiff.cost + maybeEqualCurrentDiff.cost; const omissionPreviousDiff = results.get(`${indexActual}|${indexExpected - 1}`); const omissionCost = omissionPreviousDiff.cost + (0, size_1.size)(elementExpected); const additionPreviousDiff = results.get(`${indexActual - 1}|${indexExpected}`); const additionCost = additionPreviousDiff.cost + (0, size_1.size)(elementActual); if (maybeEqualCost <= omissionCost && maybeEqualCost <= additionCost) { if (maybeEqualCurrentDiff.cost === 0) { results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({ segments: [ ...maybeEqualPreviousDiff.segments, { equal: [elementActual], cost: 0 } ], cost: maybeEqualCost })); } else { results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({ segments: [ ...maybeEqualPreviousDiff.segments, { change: [maybeEqualCurrentDiff], cost: maybeEqualCurrentDiff.cost } ], cost: maybeEqualCost })); } } else if (omissionCost <= additionCost) { results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({ segments: [ ...omissionPreviousDiff.segments, { omission: [elementExpected], cost: (0, size_1.size)(elementExpected) } ], cost: omissionCost })); } else { results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({ segments: [ ...additionPreviousDiff.segments, { addition: [elementActual], cost: (0, size_1.size)(elementActual) } ], cost: additionCost })); } results.delete(`${indexActual - 1}|${indexExpected - 1}`); } } const diff = results.get(`${actual.length - 1}|${expected.length - 1}`); if (diff.cost === 0) { return (0, EqualDiff_1.equalDiff)({ value: actual }); } return (0, simplifyDiff_1.simplifyDiff)(results.get(`${actual.length - 1}|${expected.length - 1}`)); }; const compareArrays = function (actual, expected) { if (actual.length * expected.length > maximumDiffTableSize_1.maximumDiffTableSize) { return compareArraysLinearly(actual, expected); } return compareArraysBestMatch(actual, expected); }; exports.compareArrays = compareArrays;