Skip to content

Commit ceb6ea3

Browse files
93747: Fixed and improved ArrayMoveChangeAnalyzer
1 parent c4de31e commit ceb6ea3

2 files changed

Lines changed: 35 additions & 19 deletions

File tree

src/app/core/data/array-move-change-analyzer.service.spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,28 @@ describe('ArrayMoveChangeAnalyzer', () => {
4141
], new MoveTest(0, 3));
4242

4343
testMove([
44+
{ op: 'move', from: '/2', path: '/3' },
4445
{ op: 'move', from: '/0', path: '/3' },
45-
{ op: 'move', from: '/2', path: '/1' }
4646
], new MoveTest(0, 3), new MoveTest(1, 2));
4747

4848
testMove([
49+
{ op: 'move', from: '/3', path: '/4' },
4950
{ op: 'move', from: '/0', path: '/1' },
50-
{ op: 'move', from: '/3', path: '/4' }
5151
], new MoveTest(0, 1), new MoveTest(3, 4));
5252

5353
testMove([], new MoveTest(0, 4), new MoveTest(4, 0));
5454

5555
testMove([
56+
{ op: 'move', from: '/2', path: '/3' },
5657
{ op: 'move', from: '/0', path: '/3' },
57-
{ op: 'move', from: '/2', path: '/1' }
5858
], new MoveTest(0, 4), new MoveTest(1, 3), new MoveTest(2, 4));
59+
60+
testMove([
61+
{ op: 'move', from: '/3', path: '/4' },
62+
{ op: 'move', from: '/2', path: '/4' },
63+
{ op: 'move', from: '/1', path: '/3' },
64+
{ op: 'move', from: '/0', path: '/3' },
65+
], new MoveTest(4, 1), new MoveTest(4, 2), new MoveTest(0, 3));
5966
});
6067

6168
describe('when some values are undefined (index 2 and 3)', () => {

src/app/core/data/array-move-change-analyzer.service.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,31 @@ export class ArrayMoveChangeAnalyzer<T> {
1616
* @param array2 The custom array to compare with the original
1717
*/
1818
diff(array1: T[], array2: T[]): MoveOperation[] {
19-
const result = [];
20-
const moved = [...array1];
21-
array1.forEach((value: T, index: number) => {
22-
if (hasValue(value)) {
23-
const otherIndex = array2.indexOf(value);
24-
const movedIndex = moved.indexOf(value);
25-
if (index !== otherIndex && movedIndex !== otherIndex) {
26-
moveItemInArray(moved, movedIndex, otherIndex);
27-
result.push(Object.assign({
28-
op: 'move',
29-
from: '/' + movedIndex,
30-
path: '/' + otherIndex
31-
}) as MoveOperation);
32-
}
19+
return this.getMoves(array1, array2).map((move) => Object.assign({
20+
op: 'move',
21+
from: '/' + move[0],
22+
path: '/' + move[1],
23+
}) as MoveOperation);
24+
}
25+
26+
/**
27+
* Determine a set of moves required to transform array1 into array2
28+
* The moves are returned as an array of pairs of numbers where the first number is the original index and the second
29+
* is the new index
30+
* It is assumed the operations are executed in the order they're returned (and not simultaneously)
31+
* @param array1
32+
* @param array2
33+
*/
34+
private getMoves(array1: any[], array2: any[]): number[][] {
35+
const moved = [...array2];
36+
37+
return array1.reduce((moves, item, index) => {
38+
if (hasValue(item) && item !== moved[index]) {
39+
const last = moved.lastIndexOf(item);
40+
moveItemInArray(moved, last, index);
41+
moves.unshift([index, last]);
3342
}
34-
});
35-
return result;
43+
return moves;
44+
}, []);
3645
}
3746
}

0 commit comments

Comments
 (0)