从字符串数组创建唯一组合的数组

时间:2012-07-10 13:52:10

标签: javascript algorithm combinations combinatorics

我正在写一些带有一块文本的内容,并将其分解为可用于查找类似文本块的可能的数据库查询。 (类似于我输入时生成的“类似问题”列表)基本过程:

  1. 从文字中删除停用词
  2. 删除特殊字符
  3. 从剩余的文本中创建一个独特的“词干”数组
  4. 创建一系列可能的茎阵列组合(我被卡住了......有点)
  5. 这是我到目前为止所拥有的:

        //baseList starts with an empty array
        //candList starts with the array of unique stems
        //target is where the arrays of unique combinations are stored
    
        function createUniqueCombos(baseList,candList,target){
    
        for(var i=0;i<candList.length;i++){         
    
            //copy the base List
            var newList = baseList.slice(0);
    
            //add the candidate list item to the base list copy
            newList.push(candList[i]);
    
            //add the new array to the target array
            target.push(newList);   
    
            //re-call function using new array as baseList
            //and remaining candidates as candList
            var nextCandList = candList.slice(i + 1);       
            createUniqueCombos(newList,nextCandList,target);
        }
    
    }
    

    这样可行,但是在大于25个字左右的文本块上,它会崩溃我的浏览器。我在数学上意识到可能存在大量可能的组合。我想知道的是:

    1. 有更有效的方法吗?
    2. 如何定义最小/最大组合数组长度?

3 个答案:

答案 0 :(得分:1)

我认为你的逻辑存在根本性的缺陷,因为你正在创造多少种组合。

我采取的方法是;

  1. 将文字拆分为单个字词(我们将此变量称为split_words
  2. 删除特殊字符
  3. 删除短/常用词(和,或,I,a);或者通过长度来做这件事,或者通过黑名单来更明智地做到这一点
  4. 有一个表格(例如blocks),其中包含block_id列和word
  5. 有一个SQL查询,例如

    SELECT block_id FROM blocks 
    WHERE word IN (split_words) GROUP BY block_id 
    ORDER BY COUNT(*) DESC
    
  6. 然后你会得到一个block_ids的列表,这些列表的排序取决于这些块的共同字数。

答案 1 :(得分:1)

找到上一个问题:Algorithm to find articles with similar text

其中一个答案提供了一篇文章的链接,该文章建议查找两个字符串中包含多少个相邻字符对。 [http://www.catalysoft.com/articles/StrikeAMatch.html]

示例是Java,但我确信可以轻松移植到JS:

/** @return an array of adjacent letter pairs contained in the input string */
private static String[] letterPairs(String str) {
   int numPairs = str.length()-1;
   String[] pairs = new String[numPairs];
   for (int i=0; i<numPairs; i++) {
       pairs[i] = str.substring(i,i+2);
   }
   return pairs;
}

/** @return an ArrayList of 2-character Strings. */
private static ArrayList wordLetterPairs(String str) {
   ArrayList allPairs = new ArrayList();
   // Tokenize the string and put the tokens/words into an array
   String[] words = str.split("\\s");
   // For each word
   for (int w=0; w < words.length; w++) {
       // Find the pairs of characters
       String[] pairsInWord = letterPairs(words[w]);
       for (int p=0; p < pairsInWord.length; p++) {
           allPairs.add(pairsInWord[p]);
       }
   }
   return allPairs;
}

/** @return lexical similarity value in the range [0,1] */
public static double compareStrings(String str1, String str2) {
   ArrayList pairs1 = wordLetterPairs(str1.toUpperCase());
   ArrayList pairs2 = wordLetterPairs(str2.toUpperCase());
   int intersection = 0;
   int union = pairs1.size() + pairs2.size();
   for (int i=0; i<pairs1.size(); i++) {
       Object pair1=pairs1.get(i);
       for(int j=0; j<pairs2.size(); j++) {
           Object pair2=pairs2.get(j);
           if (pair1.equals(pair2)) {
               intersection++;
               pairs2.remove(j);
               break;
           }
       }
   }
   return (2.0*intersection)/union;
}

答案 2 :(得分:0)

我的binomial coefficient class可以轻松解决您的问题。看看我answer中的代码到一个有点相关的问题。我不知道将C#代码移植到SQL存储过程是否是个好主意。将它移植到java或js并从该代码调用存储过程可能更容易。