从字符串数组创建唯一组合数组
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_id
和word
列
有一个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 并从该代码调用您存储的过程可能会更容易。
【讨论】:
以上是关于从字符串数组创建唯一组合数组的主要内容,如果未能解决你的问题,请参考以下文章