fill-path-by-diff.js 2.7 KB

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