93747: Fixed and improved ArrayMoveChangeAnalyzer

This commit is contained in:
Kristof De Langhe
2023-01-04 14:29:48 +01:00
parent c4de31ec4d
commit ceb6ea3672
2 changed files with 35 additions and 19 deletions

View File

@@ -41,21 +41,28 @@ describe('ArrayMoveChangeAnalyzer', () => {
], new MoveTest(0, 3)); ], new MoveTest(0, 3));
testMove([ testMove([
{ op: 'move', from: '/2', path: '/3' },
{ op: 'move', from: '/0', path: '/3' }, { op: 'move', from: '/0', path: '/3' },
{ op: 'move', from: '/2', path: '/1' }
], new MoveTest(0, 3), new MoveTest(1, 2)); ], new MoveTest(0, 3), new MoveTest(1, 2));
testMove([ testMove([
{ op: 'move', from: '/3', path: '/4' },
{ op: 'move', from: '/0', path: '/1' }, { op: 'move', from: '/0', path: '/1' },
{ op: 'move', from: '/3', path: '/4' }
], new MoveTest(0, 1), new MoveTest(3, 4)); ], new MoveTest(0, 1), new MoveTest(3, 4));
testMove([], new MoveTest(0, 4), new MoveTest(4, 0)); testMove([], new MoveTest(0, 4), new MoveTest(4, 0));
testMove([ testMove([
{ op: 'move', from: '/2', path: '/3' },
{ op: 'move', from: '/0', path: '/3' }, { op: 'move', from: '/0', path: '/3' },
{ op: 'move', from: '/2', path: '/1' }
], new MoveTest(0, 4), new MoveTest(1, 3), new MoveTest(2, 4)); ], new MoveTest(0, 4), new MoveTest(1, 3), new MoveTest(2, 4));
testMove([
{ op: 'move', from: '/3', path: '/4' },
{ op: 'move', from: '/2', path: '/4' },
{ op: 'move', from: '/1', path: '/3' },
{ op: 'move', from: '/0', path: '/3' },
], new MoveTest(4, 1), new MoveTest(4, 2), new MoveTest(0, 3));
}); });
describe('when some values are undefined (index 2 and 3)', () => { describe('when some values are undefined (index 2 and 3)', () => {

View File

@@ -16,22 +16,31 @@ export class ArrayMoveChangeAnalyzer<T> {
* @param array2 The custom array to compare with the original * @param array2 The custom array to compare with the original
*/ */
diff(array1: T[], array2: T[]): MoveOperation[] { diff(array1: T[], array2: T[]): MoveOperation[] {
const result = []; return this.getMoves(array1, array2).map((move) => Object.assign({
const moved = [...array1]; op: 'move',
array1.forEach((value: T, index: number) => { from: '/' + move[0],
if (hasValue(value)) { path: '/' + move[1],
const otherIndex = array2.indexOf(value); }) as MoveOperation);
const movedIndex = moved.indexOf(value); }
if (index !== otherIndex && movedIndex !== otherIndex) {
moveItemInArray(moved, movedIndex, otherIndex); /**
result.push(Object.assign({ * Determine a set of moves required to transform array1 into array2
op: 'move', * The moves are returned as an array of pairs of numbers where the first number is the original index and the second
from: '/' + movedIndex, * is the new index
path: '/' + otherIndex * It is assumed the operations are executed in the order they're returned (and not simultaneously)
}) as MoveOperation); * @param array1
} * @param array2
*/
private getMoves(array1: any[], array2: any[]): number[][] {
const moved = [...array2];
return array1.reduce((moves, item, index) => {
if (hasValue(item) && item !== moved[index]) {
const last = moved.lastIndexOf(item);
moveItemInArray(moved, last, index);
moves.unshift([index, last]);
} }
}); return moves;
return result; }, []);
} }
} }