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

Posted

技术标签:

【中文标题】从字符串数组创建唯一组合数组【英文标题】:Create array of unique combinations from array of strings 【发布时间】:2012-07-10 00:28:27 【问题描述】:

我正在写一些东西,它需要一段文本并将其分解为可能的数据库查询,这些查询可用于查找相似的文本块。 (类似于我输入时生成的“类似问题”列表)基本过程:

    从文本中删除停用词 删除特殊字符 从剩余的文本中创建一组独特的“词干” 创建一系列可能的茎数组组合(我被卡住的地方......有点)

这是我目前所拥有的:

    //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 个字左右的文本块上,它会使我的浏览器崩溃。我意识到在数学上可能存在大量可能的组合。我想知道的是:

    有没有更有效的方法来做到这一点? 如何定义最小/最大组合数组长度?

【问题讨论】:

这是一个很棒的第一个问题。欢迎来到 ***!您的浏览器可能会因使用的内存量而崩溃,或者递归过多。 你真的需要一次所有的组合吗?你不能在生成它们时立即处理它们而不是积累巨大的数组吗?还尝试将您的算法重写为迭代而不是递归。 谢谢,我作为旁观者已经有一段时间了 ;) @OlegV.Volkov 不,我不需要所有组合,我希望能够定义最小/最大长度返回的组合数组。感谢您的迭代建议。 【参考方案1】:

我认为你的逻辑存在根本缺陷,因为你创建了多少组合。

我会采取的方法是;

    将文本拆分为单个单词(我们将此变量称为split_words) 删除特殊字符 删除短/常用词(and、or、I、a);要么通过长度来做到这一点,要么更智能地通过单词黑名单来做到这一点 有一个表(例如blocks),其中包含block_idword

    有一个SQL查询比如

    SELECT block_id FROM blocks 
    WHERE word IN (split_words) GROUP BY block_id 
    ORDER BY COUNT(*) DESC
    

然后你会得到一个block_ids 的列表,这些列表的排序取决于块有多少共同的单词。

【讨论】:

感谢您的回复。在进入这一步之前,我已经在做 1、2 和 3。我正在处理服务器端的专有平台和数据库技术,并且像您建议的那样实施解决方案是我考虑过的。不幸的是,无法将我要搜索的数据分解成单个单词。【参考方案2】:

找到了上一个问题: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;

【讨论】:

这很酷。我正在尝试做的是“撒网”以找到其他“文章”来进行这种比较。一旦我弄清楚了我最初的问题,下一步可能就是这样。【参考方案3】:

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

【讨论】:

以上是关于从字符串数组创建唯一组合数组的主要内容,如果未能解决你的问题,请参考以下文章

ruby - 如何从字符串数组中生成可能的字母顺序组合?

文本到字符串数组并删除重复项

如何在java里java字符串数组合并成一个数组?

labview 数组中相邻元素抽取和组合(截取)

将两个数组 排列组合到一个数组集合 求java 代码

当数组的数量和每个数组的长度未知时生成字符组合的所有排列