123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- function diff(oldArr, newArr, equals) {
- if (!equals) {
- equals = function (a, b) {
- return a === b;
- };
- }
- oldArr = oldArr.slice();
- newArr = newArr.slice();
- var newLen = newArr.length;
- var oldLen = oldArr.length;
- var editLength = 1;
- var maxEditLength = newLen + oldLen;
- var bestPath = [{ newPos: -1, components: [] }];
- var oldPos = extractCommon(bestPath[0], newArr, oldArr, 0, equals);
- if (!oldLen
- || !newLen
- || (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen)) {
- var indices = [];
- var allCleared = !newLen && oldLen > 0;
- var allCreated = !oldLen && newLen > 0;
- for (var i = 0; i < (allCleared ? oldArr : newArr).length; i++) {
- indices.push(i);
- }
- return [{
- indices: indices,
- count: indices.length,
- added: allCreated,
- removed: allCleared
- }];
- }
- function execEditLength() {
- for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
- var basePath;
- var addPath = bestPath[diagonalPath - 1];
- var removePath = bestPath[diagonalPath + 1];
- var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
- if (addPath) {
- bestPath[diagonalPath - 1] = undefined;
- }
- var canAdd = addPath && addPath.newPos + 1 < newLen;
- var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
- if (!canAdd && !canRemove) {
- bestPath[diagonalPath] = undefined;
- continue;
- }
- if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
- basePath = clonePath(removePath);
- pushComponent(basePath.components, false, true);
- }
- else {
- basePath = addPath;
- basePath.newPos++;
- pushComponent(basePath.components, true, false);
- }
- oldPos = extractCommon(basePath, newArr, oldArr, diagonalPath, equals);
- if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
- return buildValues(basePath.components);
- }
- else {
- bestPath[diagonalPath] = basePath;
- }
- }
- editLength++;
- }
- while (editLength <= maxEditLength) {
- var ret = execEditLength();
- if (ret) {
- return ret;
- }
- }
- }
- function extractCommon(basePath, newArr, oldArr, diagonalPath, equals) {
- var newLen = newArr.length;
- var oldLen = oldArr.length;
- var newPos = basePath.newPos;
- var oldPos = newPos - diagonalPath;
- var commonCount = 0;
- while (newPos + 1 < newLen && oldPos + 1 < oldLen && equals(newArr[newPos + 1], oldArr[oldPos + 1])) {
- newPos++;
- oldPos++;
- commonCount++;
- }
- if (commonCount) {
- basePath.components.push({
- count: commonCount,
- added: false,
- removed: false,
- indices: []
- });
- }
- basePath.newPos = newPos;
- return oldPos;
- }
- function pushComponent(components, added, removed) {
- var last = components[components.length - 1];
- if (last && last.added === added && last.removed === removed) {
- components[components.length - 1] = {
- count: last.count + 1,
- added: added,
- removed: removed,
- indices: []
- };
- }
- else {
- components.push({
- count: 1,
- added: added,
- removed: removed,
- indices: []
- });
- }
- }
- function buildValues(components) {
- var componentPos = 0;
- var componentLen = components.length;
- var newPos = 0;
- var oldPos = 0;
- for (; componentPos < componentLen; componentPos++) {
- var component = components[componentPos];
- if (!component.removed) {
- var indices = [];
- for (var i = newPos; i < newPos + component.count; i++) {
- indices.push(i);
- }
- component.indices = indices;
- newPos += component.count;
- if (!component.added) {
- oldPos += component.count;
- }
- }
- else {
- for (var i = oldPos; i < oldPos + component.count; i++) {
- component.indices.push(i);
- }
- oldPos += component.count;
- }
- }
- return components;
- }
- function clonePath(path) {
- return { newPos: path.newPos, components: path.components.slice(0) };
- }
- export default function arrayDiff(oldArr, newArr, equal) {
- return diff(oldArr, newArr, equal);
- }
|