fill-path-by-diff.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var lodash_es_1 = require("lodash-es");
  4. function getMinDiff(del, add, modify) {
  5. var type = null;
  6. var min = modify;
  7. if (add < min) {
  8. min = add;
  9. type = 'add';
  10. }
  11. if (del < min) {
  12. min = del;
  13. type = 'del';
  14. }
  15. return {
  16. type: type,
  17. min: min,
  18. };
  19. }
  20. /*
  21. * https://en.wikipedia.org/wiki/Levenshtein_distance
  22. * 计算两条path的编辑距离
  23. */
  24. var levenshteinDistance = function (source, target) {
  25. var sourceLen = source.length;
  26. var targetLen = target.length;
  27. var sourceSegment, targetSegment;
  28. var temp = 0;
  29. if (sourceLen === 0 || targetLen === 0) {
  30. return null;
  31. }
  32. var dist = [];
  33. for (var i = 0; i <= sourceLen; i++) {
  34. dist[i] = [];
  35. dist[i][0] = { min: i };
  36. }
  37. for (var j = 0; j <= targetLen; j++) {
  38. dist[0][j] = { min: j };
  39. }
  40. for (var i = 1; i <= sourceLen; i++) {
  41. sourceSegment = source[i - 1];
  42. for (var j = 1; j <= targetLen; j++) {
  43. targetSegment = target[j - 1];
  44. if (lodash_es_1.isEqual(sourceSegment, targetSegment)) {
  45. temp = 0;
  46. }
  47. else {
  48. temp = 1;
  49. }
  50. var del = dist[i - 1][j].min + 1;
  51. var add = dist[i][j - 1].min + 1;
  52. var modify = dist[i - 1][j - 1].min + temp;
  53. dist[i][j] = getMinDiff(del, add, modify);
  54. }
  55. }
  56. return dist;
  57. };
  58. function fillPathByDiff(source, target) {
  59. var diffMatrix = levenshteinDistance(source, target);
  60. var sourceLen = source.length;
  61. var targetLen = target.length;
  62. var changes = [];
  63. var index = 1;
  64. var minPos = 1;
  65. // 如果source和target不是完全不相等
  66. // @ts-ignore
  67. if (diffMatrix[sourceLen][targetLen] !== sourceLen) {
  68. // 获取从source到target所需改动
  69. for (var i = 1; i <= sourceLen; i++) {
  70. var min = diffMatrix[i][i].min;
  71. minPos = i;
  72. for (var j = index; j <= targetLen; j++) {
  73. if (diffMatrix[i][j].min < min) {
  74. min = diffMatrix[i][j].min;
  75. minPos = j;
  76. }
  77. }
  78. index = minPos;
  79. if (diffMatrix[i][index].type) {
  80. changes.push({ index: i - 1, type: diffMatrix[i][index].type });
  81. }
  82. }
  83. // 对source进行增删path
  84. for (var i = changes.length - 1; i >= 0; i--) {
  85. index = changes[i].index;
  86. if (changes[i].type === 'add') {
  87. // @ts-ignore
  88. source.splice(index, 0, [].concat(source[index]));
  89. }
  90. else {
  91. // @ts-ignore
  92. source.splice(index, 1);
  93. }
  94. }
  95. }
  96. // source尾部补齐
  97. sourceLen = source.length;
  98. if (sourceLen < targetLen) {
  99. for (var i = 0; i < targetLen - sourceLen; i++) {
  100. if (source[sourceLen - 1][0] === 'z' || source[sourceLen - 1][0] === 'Z') {
  101. // @ts-ignore
  102. source.splice(sourceLen - 2, 0, source[sourceLen - 2]);
  103. }
  104. else {
  105. // @ts-ignore
  106. source.push(source[sourceLen - 1]);
  107. }
  108. }
  109. }
  110. return source;
  111. }
  112. exports.default = fillPathByDiff;
  113. //# sourceMappingURL=fill-path-by-diff.js.map