提交 a4a1fd6e 编写于 作者: J Joao

arrays.sortedDiff

上级 51c42516
......@@ -122,28 +122,43 @@ export function groupBy<T>(data: T[], compare: (a: T, b: T) => number): T[][] {
return result;
}
export interface Splice<T> {
start: number;
deleteCount: number;
inserted: T[];
}
/**
* Takes two *sorted* arrays and computes their delta (removed, added elements).
* Finishes in `Math.min(before.length, after.length)` steps.
* @param before
* @param after
* @param compare
* Diffs two *sorted* arrays and computes the splices which apply the diff.
*/
export function delta<T>(before: T[], after: T[], compare: (a: T, b: T) => number) {
export function sortedDiff<T>(before: T[], after: T[], compare: (a: T, b: T) => number): Splice<T>[] {
const result: Splice<T>[] = [];
const removed: T[] = [];
const added: T[] = [];
function pushSplice(start: number, deleteCount: number, inserted: T[]): void {
if (deleteCount === 0 && inserted.length === 0) {
return;
}
const latest = result[result.length - 1];
if (latest && latest.start + latest.deleteCount === start) {
latest.deleteCount += deleteCount;
latest.inserted.push(...inserted);
} else {
result.push({ start, deleteCount, inserted });
}
}
let beforeIdx = 0;
let afterIdx = 0;
while (true) {
if (beforeIdx === before.length) {
added.push(...after.slice(afterIdx));
pushSplice(beforeIdx, 0, after.slice(afterIdx));
break;
}
if (afterIdx === after.length) {
removed.push(...before.slice(beforeIdx));
pushSplice(beforeIdx, before.length - beforeIdx, []);
break;
}
......@@ -156,15 +171,35 @@ export function delta<T>(before: T[], after: T[], compare: (a: T, b: T) => numbe
afterIdx += 1;
} else if (n < 0) {
// beforeElement is smaller -> before element removed
removed.push(beforeElement);
pushSplice(beforeIdx, 1, []);
beforeIdx += 1;
} else if (n > 0) {
// beforeElement is greater -> after element added
added.push(afterElement);
pushSplice(beforeIdx, 0, [afterElement]);
afterIdx += 1;
}
}
return result;
}
/**
* Takes two *sorted* arrays and computes their delta (removed, added elements).
* Finishes in `Math.min(before.length, after.length)` steps.
* @param before
* @param after
* @param compare
*/
export function delta<T>(before: T[], after: T[], compare: (a: T, b: T) => number): { removed: T[], added: T[] } {
const splices = sortedDiff(before, after, compare);
const removed: T[] = [];
const added: T[] = [];
for (const splice of splices) {
removed.push(...before.slice(splice.start, splice.start + splice.deleteCount));
added.push(...splice.inserted);
}
return { removed, added };
}
......
......@@ -94,7 +94,51 @@ suite('Arrays', () => {
}
});
test('delta', function () {
test('sortedDiff', function () {
function compare(a: number, b: number): number {
return a - b;
}
let d = arrays.sortedDiff([1, 2, 4], [], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 3, inserted: [] }
]);
d = arrays.sortedDiff([], [1, 2, 4], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 0, inserted: [1, 2, 4] }
]);
d = arrays.sortedDiff([1, 2, 4], [1, 2, 4], compare);
assert.deepEqual(d, []);
d = arrays.sortedDiff([1, 2, 4], [2, 3, 4, 5], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 1, inserted: [] },
{ start: 2, deleteCount: 0, inserted: [3] },
{ start: 3, deleteCount: 0, inserted: [5] },
]);
d = arrays.sortedDiff([2, 3, 4, 5], [1, 2, 4], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 0, inserted: [1] },
{ start: 1, deleteCount: 1, inserted: [] },
{ start: 3, deleteCount: 1, inserted: [] },
]);
d = arrays.sortedDiff([1, 3, 5, 7], [5, 9, 11], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 2, inserted: [] },
{ start: 3, deleteCount: 1, inserted: [9, 11] }
]);
d = arrays.sortedDiff([1, 3, 7], [5, 9, 11], compare);
assert.deepEqual(d, [
{ start: 0, deleteCount: 3, inserted: [5, 9, 11] }
]);
});
test('delta sorted arrays', function () {
function compare(a: number, b: number): number {
return a - b;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册