当前位置:   article > 正文

js比较文本内容_js比较span中内容是否一致

js比较span中内容是否一致

比较两段文本内容的差异,网上都没有合适的算法,只能自己写了

,效果如下图 

  1. <html>
  2. <head>
  3. <meta charset="UTF-8">
  4. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  5. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  6. <title></title>
  7. </head>
  8. <body>
  9. 文本1<br>
  10. <textarea id="text1" cols="100" rows="10">张三李四</textarea><br>
  11. 文本2<br>
  12. <textarea id="text2" cols="100" rows="10">李四张三张三</textarea><br>
  13. <button type="button" onclick="compare()">比对</button><br><br>
  14. 结果1<br>
  15. <pre id="result1"></pre>
  16. 结果2<br>
  17. <pre id="result2"></pre>
  18. <script type="text/javascript">
  19. function compare() {
  20. // 获取要比对的文本
  21. let text1 = document.getElementById('text1').value;
  22. let text2 = document.getElementById('text2').value;
  23. // 进行比对
  24. let {result1, result2} = getHighlight(text1, text2);
  25. // 渲染比对结果
  26. document.getElementById('result1').innerHTML = result1;
  27. document.getElementById('result2').innerHTML = result2;
  28. }
  29. /**
  30. * 获取高亮文本
  31. *
  32. * @param text1 文本1
  33. * @param text2 文本2
  34. * @param highlightBefore 高亮前缀
  35. * @param highlightAfter 高亮后缀
  36. * @return {result2: string, result1: string} 高亮后的字符串
  37. */
  38. function getHighlight(text1, text2, highlightBefore, highlightAfter) {
  39. // 初始化高亮文本
  40. highlightBefore = highlightBefore ? highlightBefore : '<span style="color:red;">';
  41. highlightAfter = highlightAfter ? highlightAfter : '</span>';
  42. // 字符数组
  43. let char1s = [];
  44. let char2s = [];
  45. // 偏移量
  46. let char2Index = 0;
  47. // 初始化字符数组对象
  48. for (let i in text1) {
  49. char1s.push({
  50. value: text1[i],
  51. highlight: false
  52. });
  53. }
  54. for (let i in text2) {
  55. char2s.push({
  56. value: text2[i],
  57. highlight: false
  58. });
  59. }
  60. for (let i = 0; i < char1s.length; i++, char2Index++) {
  61. console.log(i, char2Index);
  62. // 如果文本1结尾有东西
  63. if (char2Index > char2s.length - 1) {
  64. char1s[i].highlight = true;
  65. continue;
  66. }
  67. let char1 = char1s[i].value;
  68. let char2 = char2s[char2Index].value;
  69. console.log(`char1: ${char1}, char2: ${char2}`);
  70. // 如果字符相等
  71. if (char1 === char2) {
  72. continue;
  73. }
  74. /**
  75. * 初始化比对粒度
  76. *
  77. * 如果连续3个一样的字符,就说明比对成功
  78. * 比对粒度太大,细小的部分可能比对不出来
  79. * 比对粒度太小,重复率高的话容易被比对出来,容易比对错
  80. * 正常调成3就够了,除非重复率特别高的,可以往上调,但建议不超过5
  81. * 最低也不要低于2,不可调成1,否则只要有一个字符一样的,就会被识别出来
  82. */
  83. let granularity;
  84. if (char1s.length < 10) {
  85. granularity = 2;
  86. } else if (char1s.length < 1000) {
  87. granularity = 3;
  88. } else if (char1s.length < 100000) {
  89. granularity = 4;
  90. } else {
  91. granularity = 5;
  92. }
  93. // 快到结尾时调小比对粒度
  94. if (i > char1s.length - granularity) {
  95. granularity = char1s.length - i;
  96. console.log('修改比对粒度', granularity);
  97. }
  98. // 如果剩余长度小于比对粒度,则不进行比对
  99. if (char1s.length - i < granularity) {
  100. break;
  101. }
  102. // 用来判断是否找到一样的
  103. let end = -1;
  104. // 进行循环比对
  105. // j: 从char2s的哪个索引开始比对
  106. for (let j = char2Index + 1; j < char2s.length - granularity + 1; j++) {
  107. // 比对factor个
  108. let equals = true;
  109. for (let k = j, offset = 0; k < j + granularity; k++, offset++) {
  110. console.log('第' + offset + '次比对', char1s[i + offset].value, char2s[k].value, i + offset, k);
  111. if (char1s[i + offset].value !== char2s[k].value) {
  112. equals = false;
  113. break;
  114. }
  115. }
  116. // 如果相等,结束比对
  117. if (equals) {
  118. end = j;
  119. console.log('比对成功, end=' + end + ', 比对粒度' + granularity);
  120. break;
  121. } else {
  122. console.log('比对失败, 比对粒度' + granularity);
  123. }
  124. }
  125. console.log('比对结束,end=' + end);
  126. // 如果找到了
  127. if (end !== -1) {
  128. for (let k = char2Index; k < end; k++) {
  129. char2s[k].highlight = true;
  130. char2Index++;
  131. console.log('设置高亮', char2s[k]);
  132. }
  133. }
  134. // 如果没找到,就让自己高亮
  135. else {
  136. char1s[i].highlight = true;
  137. char2Index--;
  138. console.log('找不到' + char1);
  139. }
  140. }
  141. // 遍历最后多出来的文本2,全部高亮
  142. for (let i = char2Index; i < char2s.length; i++) {
  143. char2s[i].highlight = true;
  144. }
  145. // 将字符数组对象转换成高亮形式
  146. let result1 = char1s.map(char => char.highlight ? highlightBefore + char.value + highlightAfter : char.value).join('');
  147. let result2 = char2s.map(char => char.highlight ? highlightBefore + char.value + highlightAfter : char.value).join('');
  148. return {result1, result2};
  149. }
  150. </script>
  151. </body>
  152. </html>

另外提供了Java版本,算法是一样的,翻译过来的而已

Char.java

  1. /**
  2. * 用于描述一个字符
  3. */
  4. class Char {
  5. /**
  6. * 字符
  7. */
  8. private Character value;
  9. /**
  10. * 高亮
  11. */
  12. private Boolean highlight;
  13. public Char(Character value) {
  14. this.value = value;
  15. this.highlight = false;
  16. }
  17. public Character getValue() {
  18. return value;
  19. }
  20. public void setValue(Character value) {
  21. this.value = value;
  22. }
  23. public Boolean getHighlight() {
  24. return highlight;
  25. }
  26. public void setHighlight(Boolean highlight) {
  27. this.highlight = highlight;
  28. }
  29. @Override
  30. public String toString() {
  31. return "Char{" +
  32. "value=" + value +
  33. ", highlight=" + highlight +
  34. '}';
  35. }
  36. }

CompareResult.java

  1. /**
  2. * 比对结果
  3. *
  4. * @author 猴哥
  5. */
  6. public class CompareResult {
  7. /**
  8. * 结果1
  9. */
  10. private String result1;
  11. /**
  12. * 结果2
  13. */
  14. private String result2;
  15. public CompareResult(String result1, String result2) {
  16. this.result1 = result1;
  17. this.result2 = result2;
  18. }
  19. public String getResult1() {
  20. return result1;
  21. }
  22. public void setResult1(String result1) {
  23. this.result1 = result1;
  24. }
  25. public String getResult2() {
  26. return result2;
  27. }
  28. public void setResult2(String result2) {
  29. this.result2 = result2;
  30. }
  31. @Override
  32. public String toString() {
  33. return "CompareResult{" +
  34. "result1='" + result1 + '\'' +
  35. ", result2='" + result2 + '\'' +
  36. '}';
  37. }
  38. }

 CompareUtil.java

  1. import java.util.Arrays;
  2. import java.util.Optional;
  3. import java.util.stream.Collectors;
  4. /**
  5. * 比较字符串工具类
  6. *
  7. * @author 猴哥
  8. */
  9. public class CompareUtil {
  10. private CompareUtil() {}
  11. /**
  12. * 获取高亮文本
  13. *
  14. * @param text1 文本1
  15. * @param text2 文本2
  16. * @param highlightBefore 高亮前缀
  17. * @param highlightAfter 高亮后缀
  18. * @return 高亮后的字符串
  19. */
  20. public static CompareResult compare(String text1, String text2, String highlightBefore, String highlightAfter) {
  21. // 判断非空
  22. text1 = Optional.ofNullable(text1).orElse("");
  23. text2 = Optional.ofNullable(text2).orElse("");
  24. // 字符数组
  25. Char[] char1s = new Char[text1.length()];
  26. Char[] char2s = new Char[text2.length()];
  27. // 偏移量
  28. int char2Index = 0;
  29. // 初始化字符数组对象
  30. for (int i = 0; i < text1.length(); i++) {
  31. char1s[i] = new Char(text1.charAt(i));
  32. }
  33. for (int i = 0; i < text2.length(); i++) {
  34. char2s[i] = new Char(text2.charAt(i));
  35. }
  36. for (int i = 0; i < char1s.length; i++, char2Index++) {
  37. // 如果文本1结尾有东西
  38. if (char2Index > char2s.length - 1) {
  39. char1s[i].setHighlight(true);
  40. continue;
  41. }
  42. char char1 = char1s[i].getValue();
  43. char char2 = char2s[char2Index].getValue();
  44. System.out.println("char1: " + char1 + ", char2: " + char2);
  45. // 如果字符相等
  46. if (char1 == char2) {
  47. continue;
  48. }
  49. /*
  50. * 初始化比对粒度
  51. *
  52. * 如果连续3个一样的字符,就说明比对成功
  53. * 比对粒度太大,细小的部分可能比对不出来
  54. * 比对粒度太小,重复率高的话容易被比对出来,容易比对错
  55. * 正常调成3就够了,除非重复率特别高的,可以往上调,但建议不超过5
  56. * 最低也不要低于2,不可调成1,否则只要有一个字符一样的,就会被识别出来
  57. */
  58. int granularity;
  59. if (char1s.length < 10) {
  60. granularity = 2;
  61. } else if (char1s.length < 1000) {
  62. granularity = 3;
  63. } else if (char1s.length < 100000) {
  64. granularity = 4;
  65. } else {
  66. granularity = 5;
  67. }
  68. // 快到结尾时调小比对粒度
  69. if (i > char1s.length - granularity) {
  70. granularity = char1s.length - i;
  71. System.out.println("修改比对粒度: " + granularity);
  72. }
  73. // 如果剩余长度小于比对粒度,则不进行比对
  74. if (char1s.length - i < granularity) {
  75. break;
  76. }
  77. // 用来判断是否找到一样的
  78. int end = -1;
  79. // 进行循环比对
  80. // j: 从char2s的哪个索引开始比对
  81. for (int j = char2Index + 1; j < char2s.length - granularity + 1; j++) {
  82. // 比对factor个
  83. boolean equals = true;
  84. for (int k = j, offset = 0; k < j + granularity; k++, offset++) {
  85. System.out.println("第" + offset + "次比对 " + char1s[i + offset].getValue() + " " + char2s[k].getValue() + " " + (i + offset) + " " + k);
  86. if (!char1s[i + offset].getValue().equals(char2s[k].getValue())) {
  87. equals = false;
  88. break;
  89. }
  90. }
  91. // 如果相等,结束比对
  92. if (equals) {
  93. end = j;
  94. System.out.println("比对成功, end=" + end + ", 比对粒度" + granularity);
  95. break;
  96. } else {
  97. System.out.println("比对失败, 比对粒度" + granularity);
  98. }
  99. }
  100. System.out.println("比对结束,end=" + end);
  101. // 如果找到了
  102. if (end != -1) {
  103. for (int k = char2Index; k < end; k++) {
  104. char2s[k].setHighlight(true);
  105. char2Index++;
  106. System.out.println("设置高亮" + char2s[k]);
  107. }
  108. }
  109. // 如果没找到,就让自己高亮
  110. else {
  111. char1s[i].setHighlight(true);
  112. char2Index--;
  113. System.out.println("找不到" + char1);
  114. }
  115. }
  116. // 遍历最后多出来的文本2,全部高亮
  117. for (int i = char2Index; i < char2s.length; i++) {
  118. char2s[i].setHighlight(true);
  119. }
  120. // 初始化高亮前缀、后缀
  121. final String before = Optional.ofNullable(highlightBefore).orElse("<span style=\"color:red;\">");
  122. final String after = Optional.ofNullable(highlightAfter).orElse("</span>");
  123. // 将字符数组对象转换成高亮形式
  124. String result1 = Arrays.stream(char1s)
  125. .map(char1 -> char1.getHighlight() ? before + char1.getValue() + after : char1.getValue() + "")
  126. .collect(Collectors.joining());
  127. String result2 = Arrays.stream(char2s)
  128. .map(char2 -> char2.getHighlight() ? before + char2.getValue() + after : char2.getValue() + "")
  129. .collect(Collectors.joining());
  130. return new CompareResult(result1, result2);
  131. }
  132. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/796943
推荐阅读
相关标签