string-overlap-matching-degree

计算字符串重叠/匹配度计算

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/501646/1429885/string-overlap-matching-degree.js

  1. /* 当前版本:v1.1 */
  2. /**
  3. * 重叠匹配度
  4. * @author: zhuangjie
  5. * @date: 2024-07-23
  6. */
  7. function overlapMatchingDegreeForObjectArray(keyword = "", objArr = [], fun = (obj) => [], {sort = "desc", onlyHasScope = false, scopeForObjArrContainer} = {}) {
  8. const scopeForData = objArr.map(item => overlapMatchingDegree(keyword, fun(item), sort));
  9. // scope与 objArr 同步排序
  10. sortAndSync(scopeForData, objArr, sort);
  11. if (Array.isArray(scopeForObjArrContainer)) {
  12. scopeForObjArrContainer.push(...scopeForData);
  13. }
  14.  
  15. return onlyHasScope ? objArr.filter((_, index) => scopeForData[index] !== 0) : objArr;
  16. }
  17. /**
  18. * 计算匹配度外层封装工具
  19. * @param {string} keyword - 匹配字符串1
  20. * @param {Object | Arrayy} topicWeighs - 匹配字符串2与它的权重
  21. * @returns {number} 匹配度分数
  22. */
  23. function overlapMatchingDegree(keyword, topicWeighs = {}, sort = "desc") {
  24. if (Array.isArray(topicWeighs)) {
  25. const weightMultiplier = sort === "asc" ? 1 : -1;
  26. topicWeighs = Object.fromEntries(topicWeighs.map((topic, index) => [topic, (index + 1) * weightMultiplier]));
  27. }
  28. return Object.keys(topicWeighs).reduce((totalScore, topic) => {
  29. const currentScore = topicWeighs[topic];
  30. const overlapLengthBlocksMap = findOverlapBlocks(keyword, topic);
  31. return totalScore + Object.entries(overlapLengthBlocksMap).reduce((sum, [length, blocks]) => {
  32. return sum + blocks.length * Math.pow(currentScore, Number(length));
  33. }, 0);
  34. }, 0);
  35. }
  36. /**
  37. * 查找重叠匹配块(入口函数)
  38. * @param {*} str1
  39. * @param {*} str2
  40. * @returns 返回重叠块 如:{"2": ["好用","推荐"],"3": ["好用推荐"]}
  41. * 算法核心思想:
  42. * -----------------------------------------------------
  43. * sumatrapdf* | sumatrapdf* | sumatrapdf*
  44. * pdf- | pdf- | pdf-
  45. * ------------------------------------------------------
  46. */
  47. function findOverlapBlocks(str1 = "", str2 = "") {
  48. const alignmentHub = {};
  49. const str1Len = str1.length;
  50. const str2Len = str2.length;
  51. const minLen = Math.min(str1Len, str2Len);
  52.  
  53. for (let offset = 1 - str2Len; offset < str1Len; offset++) {
  54. const start = Math.max(0, offset);
  55. const end = Math.min(str1Len, str2Len + offset);
  56. const overlapStr1 = str1.slice(start, end);
  57. const overlapStr2 = str2.slice(start - offset, end - offset);
  58.  
  59. const alignmentContent = alignment(overlapStr1, overlapStr2);
  60. for (const [len, blocks] of Object.entries(alignmentContent)) {
  61. alignmentHub[len] = alignmentHub[len] ? [...new Set([...alignmentHub[len], ...blocks])] : blocks;
  62. }
  63. }
  64. return alignmentHub;
  65. }
  66. // 对齐
  67. function alignment(str1 = "", str2 = "") {
  68. const overlappingBlocks = {};
  69. let currentBlock = "";
  70.  
  71. for (let i = str1.length - 1; i >= 0; i--) {
  72. if (str1[i] === str2[i]) {
  73. currentBlock = str1[i] + currentBlock;
  74. } else if (currentBlock.length > 0) {
  75. const len = currentBlock.length;
  76. overlappingBlocks[len] = overlappingBlocks[len] || [];
  77. if (!overlappingBlocks[len].includes(currentBlock)) {
  78. overlappingBlocks[len].push(currentBlock);
  79. }
  80. currentBlock = "";
  81. }
  82. }
  83. if (currentBlock.length > 0) {
  84. const len = currentBlock.length;
  85. overlappingBlocks[len] = overlappingBlocks[len] || [];
  86. if (!overlappingBlocks[len].includes(currentBlock)) {
  87. overlappingBlocks[len].push(currentBlock);
  88. }
  89. }
  90.  
  91. return overlappingBlocks;
  92. }
  93. // 【同步排序算法】
  94. function sortAndSync(arr1, arr2, order = 'desc') {
  95. const compare = order === 'asc' ? (a, b) => a - b : (a, b) => b - a;
  96. arr1.map((v, i) => [v, arr2[i]])
  97. .sort((a, b) => compare(a[0], b[0]))
  98. .forEach(([v, o], i) => {
  99. arr1[i] = v;
  100. arr2[i] = o;
  101. });
  102. }
  103.  
  104.  
  105. // 【算法测试1】
  106. // console.log("-- 算法测试开始 --")
  107. // console.log(findOverlapBlocks("[推荐]sumatrapdf非常好用","pdf 推荐"))
  108. // console.log("-- 算法测试结束 --")
  109.  
  110. // 【算法测试2】
  111. // console.log("匹配度:", overlapMatchingDegree("好用的pdf工具", { "sumatrapdf": 10, "小而好用的pdf阅读器": 8, "https://www.sumatrapdfreader.org/downloadafter": 3 }));

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址