【问题标题】:How to find similar sequences between two texts in javascript如何在javascript中找到两个文本之间的相似序列
【发布时间】:2021-08-09 09:08:16
【问题描述】:

我正在尝试比较两个不同的文本以存储相似的序列。但是,我很难找到一种方法来做到这一点。我正在寻找的是这样的:

假设我们有两个文本:

文本 1: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。Exceptioneur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est here。”

文本 2: “嗨,我正在寻找学习编程的课程。Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。 Exceptioneur sint occaecat idk 我应该在这里写下什么。”

我想在两个文本中获得相似的序列。在这种情况下是:

“Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariaatur。”

但是有两条规则:

1 - 相似性应该由一组句子组成(因此他们必须至少造一个句子);任何不完整的句子都应该被忽略。

例如,这应该存储:“Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur。”

但不是紧随其后的三个单词序列:“Excepteur sint occaecat”

2 - 日常表达应该被忽略。 (例如:“希望尽快收到您的来信”、“上帝保佑您”等)

如何编写这个算法,有什么办法吗?

【问题讨论】:

    标签: javascript algorithm similarity


    【解决方案1】:

    请使用此代码。

    //You can add more expressions
    const everyday_expressions = ["Hello.", "Hope to hear from you soon", "God bless you"];
    
    const text1 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est here.";
    const text2 = "Hi, I'm looking for a course to learn programming. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat idk what I'm supposed to write down here.";
    
    const arr_text1 = text1.split(".").map(val=>val.trim()+".");
    const arr_text2 = text2.split(".").map(val=>val.trim()+".");
    
    const result = arr_text1.filter(val => (val.length > 1 && arr_text2.indexOf(val) > -1) && everyday_expressions.indexOf(val) == -1);
    console.log(result);
    

    【讨论】:

      【解决方案2】:

      如果性能很重要,请考虑使用二分搜索:

      const commonExpressions = [
        'hope to hear from you soon',
        'god bless you',
        'see you tomorrow',
        /* ... */
      ];
      
      commonExpressions.sort(); // or store them sorted
      
      function binarySearch(arr, str) {
        let low = 0, high = arr.length - 1;
        while (low <= high) {
          const mid = Math.floor((low + high) / 2);
          const c = arr[mid].localeCompare(str);
          if (c < 0) low = mid + 1;
          else if (c > 0) high = mid - 1;
          else return true;
        }
        return false;
      }
      
      function findSimilarities(text1, text2) {
        const rawSentences1 = text1.split('.').map(s => s.trim());
        const sentences1 = rawSentences1
          .map(s => s.toLowerCase())
          .filter(s => s && !binarySearch(commonExpressions, s));
      
        const sentences2 = text2
          .split('.')
          .map(s => s.trim().toLowerCase())
          .filter(s => s && !binarySearch(commonExpressions, s));
        sentences2.sort();
      
        let result = sentences1.reduce((matches, s, i) => {
          if (binarySearch(sentences2, s)) {
            matches.push(i);
          }
          return matches;
        }, []).map(i => rawSentences1[i]).join('. ');
      
        return result && result + '.';
      }
      
      let text1 = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est here.`;
      
      let text2 = `Hi, I'm looking for a course to learn programming. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat idk what I'm supposed to write down here.`;
      
      console.log(findSimilarities(text1, text2));

      我在这里假设您想要不区分大小写的句子比较,所以我使用toLowerCase()

      请注意,此解决方案是不对称的,即交换参数可能会导致不同的结果。原因可能如下:

      1. 由于不区分大小写比较,匹配的句子不必严格相等。在这种情况下,第一个文本的大写是结果字符串中使用的大写。这也是我们将第一个文本中的句子以原始大写形式存储在rawSentences1 中的原因。如果我们不这样做,结果字符串将是小写的。
      2. 匹配的句子按照它们在第一个文本中的顺序出现在结果字符串中。它们在第二个文本中可能有不同的顺序,但仍被视为匹配项。相反,如果您想获得尽可能多的匹配句子,以便它们在两个文本中以相同的顺序出现,您应该阅读longest common subsequence problem

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-21
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        • 2012-02-12
        • 2017-09-23
        • 2016-12-14
        • 1970-01-01
        相关资源
        最近更新 更多