正则表达式(Javascript)-获取一个加扰的单词并找到一个未加扰的匹配项
我有一个英语词典中所有单词的列表(270000多个单词),存储在一个名为正则表达式(Javascript)-获取一个加扰的单词并找到一个未加扰的匹配项,javascript,regex,Javascript,Regex,我有一个英语词典中所有单词的列表(270000多个单词),存储在一个名为theList的变量中。 我有一个加扰的单词word,我想通过匹配单词列表来解读它。 起初,我认为下面的代码可以做到这一点,但效果不太好 var theList; // Contains all the words in the English dictionary. var word = "iexospensr"; // The word I want to unscramble. var matches = word
theList
的变量中。
我有一个加扰的单词word
,我想通过匹配单词列表来解读它。
起初,我认为下面的代码可以做到这一点,但效果不太好
var theList; // Contains all the words in the English dictionary.
var word = "iexospensr"; // The word I want to unscramble.
var matches = word.match(new RegExp("^["+word+"]{"+word.length+"}$", "gim"));
我本以为“表达式”是解读的结果,但我得到了更多的结果(如下所列)
怪诞,表现者,表情,讽刺,等孢子,非人格,非十字架,爱管闲事,开放,压迫,压迫者,华丽,养老金,养老金,养老金领取者,佩珀罗尼斯,波斯人,人格,皮皮皮尼斯,皮皮西尼斯,穷人,穷人,穷人,占有,占有,占有,预暴露,预暴露,预暴露,先验,普里西尼,财产,适当性、复吸、抑制、抑制、抑制、利血平、反应、反应、成熟、罗皮内斯、罗西内斯、宁静、性感、六便士、剪彩、酸痛、喷丝女
也许,如果我能找到一个方法来告诉正则表达式在字符串<代码>单词< /代码>中的每一个字母一次,而不考虑字母的顺序。所以最终的结果将是这些字母的组合数组,而不是排列(我现在看到的)
任何帮助都将不胜感激
编辑:
我认为应该走的路是:
1.查找加扰词的所有组合
2.将它们与单词列表匹配以检查有效性
如果您有更好的解决方案(性能方面),它会有所帮助
这个问题的最佳解决方案似乎是按字母表重新排列字谜,以及整个单词列表,并将单词与列表中的每个项目进行匹配
代码如下:
var textList; // the entire dictionary
var list = textList.match(/^.*$/gim);
var sortedList = [];
list.forEach(function(element, index, array) {
sortedList[index] = element.split("").sort().join("");
});
function unscramble(word)
{
word = word.toUpperCase().split("").sort().join("");
var matches = [];
for (var i = 0; i < list.length; i++) {
if (word.indexOf(sortedList[i]) >= 0) {
if (!matches[list[i].length])
matches[list[i].length] = [];
matches[list[i].length].push(list[i]);
}
}
return matches;
}
var textList;//整本字典
var list=textList.match(/^.*$/gim);
var-sortedList=[];
forEach(函数(元素、索引、数组){
sortedList[索引]=元素.split(“”).sort().join(“”);
});
功能解读(word)
{
word=word.toUpperCase().split(“”).sort().join(“”);
var匹配=[];
对于(变量i=0;i=0){
如果(!匹配[list[i].length])
匹配项[列表[i]。长度]=[];
匹配[list[i].length].push(list[i]);
}
}
返回比赛;
}
我不知道正则表达式是否是这项工作的最佳工具。你正在构建的正则表达式最终将成为
"^[iexospensr]{10}$"
它匹配由字符类中的任何字母组成的任何10个字母的单词[iexospensr]
也许,如果我能找到一种方法来告诉正则表达式,不管字符串的顺序如何,只考虑字符串中的每一个字母。
您可以使用word.length
不同的正则表达式来实现这一点,但有些字母会重复。如果你对拼凑的单词中的字母进行排序,然后搜索每个字母重复次数正确的单词,你会更接近。例如,两个e、两个s、一个x等等。我认为更好的方法不会使用正则表达式。取而代之的是,它将根据您的加扰单词测试列表中的每个成员,方法是遍历单词的字符,并查看该字符是否存在于列表中的单词中。每次找到一个字符时,它都可以将该字符标记为“已使用”
这里有一些东西可以将角色位置标记为“已使用”:
正则表达式虽然功能强大,但并不是万能的解决方案
在这样的情况下,最好构建自己的解决方案:首先删除所有与所需长度不匹配的单词,然后开始比较字母
根据字典的长度,您可以构建不同的优化。这里有一个想法。构造初始查找数据将很慢,但查找匹配项应该很简单。但是,您应该只构建一次字典并加载它!每次重新计算都是浪费时间
我假设您只使用拉丁字母表(即英文书写),所有内容都不区分大小写,并且您不使用数字…等等。所以你只有A-Z个字符
对于字典中的每个单词,根据每个字母出现的次数构建一个“哈希”。散列数组将有26个位置。每个位置将记录遇到该位置的特定字符的次数。(例如,A位于第一个数组位置/索引0;Z位于第26个/索引25)
要稍微作弊,可以将结果存储为一对字符串。如果有的话,很少有单词的一个字母有9个重复,所以每个字母只有一个“数字”就可以了。例如:“该”变为“00001000000000000000000”;“帽子”变为“100000000001000000000”;“该”变为“10000002000000”
加载预计算字典。将哈希值用作键值对中的键,并将集合用作值。将具有相同关键字的每个单词附加到该关键字集合的末尾
对加扰字执行相同的哈希算法,并查找密钥。输出键引用的集合
编辑1:
如果预先构建一个字典是不可行的,那么使用一个变体,创建一个以字母为键的关联数组/字典,找到它的次数作为值。在计算这个之前,比较长度,如果字符串的长度不同,那么不要费心比较,因为你知道它们不匹配。计算源(加扰)和目标(可能匹配)的这些数组后,比较关联数组中的键和值
编辑2:
按照与上面相同的思路,对源和目标字符串中的字符进行排序
function checkUsed(o, which) {
if (o[which] != null) {
o[which] = 1;
return false;
}
return true;
}
var usedMap = [];
if (checkUsed(usedMap, 5) == false) {
...
}
//WARNING, untested code
alphabet = 'qwertyuiopasdfghjklzxcvbnm';
function empty_frequences(){
var freqs = {};
var i=;
for(i=0; i<alphabet.length; i++){
freqs[alphabet[i]] = 0;
}
return freqs;
}
function frequences(str){
var freqs = empty_frequences();
var i;
for(i=0; i<str.length; i++){
freqs[str[i]] += 1;
}
}
function matcher(word){
//returns a function that matchs against this word
var word_freqs = frequences(word);
function do_the_match(word2){
var freqs2 = frequences(word2);
var i, c;
for(i=0; i<alphabet.length; i++){
c = alphabet[i]
if(freqs[c] > freqs2[c]){return false;}
//change > to != to allow only strict anagrams
}
return true;
}
return do_the_match;
}
function main(word, dict){
var mf = matcher(word);
var i, matcheds = [];
for(i=0; i<dict.length; i++){
if(mf(dict[i])){ matcheds.push(dict[i]); }
}
return matcheds;
}
> var words = 'exceptional extraordinary retinas retains retsina antsier nastier retrains starfish';
> words.match(/\b([aeinrst])(?!\1)([aeinrst])(?!\1|\2)([aeinrst])(?!\1|\2|\3)([aeinrst])(?!\1|\2|\3|\4)([aeinrst])(?!\1|\2|\3|\4|\5)([aeinrst])(?!\1|\2|\3|\4|\5|\6)([aeinrst])\b/ig)
[ 'retinas', 'retains', 'retsina', 'antsier', 'nastier' ]