如何制作与单词中的任何字母匹配X次的正则表达式?

时间:2012-08-27 03:55:48

标签: javascript regex

最近,我开始制作一个文字游戏,其中包括用另一个单词的字母制作单词。例如,如果您有单词“Teutonic”,您可以制作“Tonic”,“tone”等。在游戏中,您只能使用单词中可用的字母,而不是重复它们。这意味着虽然“补品”在上面的例子中是有效的,但“tonico”不会,因为“Teutonic”中只有一个“o”。

我的问题基本上是,如何制作一个正则表达式,以便它搜索一个字母的实例并记住它,以便在循环后面给出相同的字母时不会再找一次?

所以如果你有“Teutonic”并且你正在使用正则表达式搜索“tonico”(“t”,“o”,“n”,“i”,“c”,“o”)中的每个字母,你会得到每个人的“真实”,除了最后一个“o”。

如果你有“铅笔”这个词,你会得到“笔”,“线”和“桩”的真实,但不是“管道”。

或者,如果你有“小”,你会得到“购物中心”,“购物中心”而不是“大众”。


编辑:

非常感谢您的所有快速回复! 我怀疑采用正则表达式方法是不可能的,但我想确定一下。相反,我用数组方法进行了一些实验,认为我没有走得太远。

再次感谢你们!

4 个答案:

答案 0 :(得分:6)

将字符串拆分为数组,然后与数组进行比较。

function checkStr(str1, str2) {
  var arr1 = str1.split(''),
      arr2 = str2.split(''),
      i,j;
  for (i = 0; i < arr2.length; i++) {
     if ((j= arr1.indexOf(arr2[i])) === -1) {
        return false;
     } 
     arr1.splice(j, 1);
  }
  return true;
}
// usage
checkStr('small', 'mall');

答案 1 :(得分:2)

正则表达式不适合这项任务。我会为源和目标字符串构建一个(character -> occurrences)的哈希值,然后比较目标哈希中的计数,以确保它们都是&lt; =源哈希中的相应计数。

如果你将这个逻辑粘贴在一个对象中,你可以只构建一次源哈希,然后多次测试它(jsFiddle version):

function Comparer(sourceStr)
{
    this.buildHash = function(str)
    {
        var hash = new Object();
        for (var i in str)
            hash[str[i]] = (hash[str[i]] || 0) + 1;

        return hash
    };

    this.check = function(testStr)
    {
        var hash = this.buildHash(testStr);

        for (var c in hash)
            if ((this.sourceHash[c] || 0) < hash[c])
                return false;

        return true;
    };     

    this.source = sourceStr;
    this.sourceHash = this.buildHash(sourceStr);
};

var comp = new Comparer("teutonic");
alert(comp.check("tonic"));  // true
alert(comp.check("tint"));   // true
alert(comp.check("tonico")); // false
alert(comp.check("asdf"));   // false

答案 2 :(得分:0)

我不确定这是正则表达式的合适用例吗?我认为,因为你希望使用原始单词中的字母,以不同的顺序显示它们,所以表达式不再是“常规”。

我想如果可以这样做,就需要使用非常复杂的反向引用。

我会使用某种自定义(或预先存在的特定于域)算法对此进行攻击。

但我必须承认我不是一名正则表达专家,所以很高兴被证明是错误的!

答案 3 :(得分:0)

// It may not matter, but you can also compare strings without creating arrays.

String.prototype.contains= function(word){
    var seed= String(this), i= 0, len= word.length, next= '';
    while(i<len){
        next= word.charAt(i++);
        if(seed.indexOf(next)== -1) return false;
        seed= seed.replace(next, '');
    }
    return word;
}


//testing 
var startword= 'teutonic',report='startword= '+startword, 
list= ['ton', 'on', 'out', 'tout', 'tone', 'tonic', 'tune', 'nice', 
'note', 'not','tot', 'tote', 'ice', 'tic', 'nick', 'cone', 'con', 'cut', 'cute'];

var failed=list.filter(function(itm){
    return !startword.contains(itm);
});

report+= failed.length? '\n'+failed.length+' incorrect: '+failed+';\n':'';
report+=list.length+' correct: '+list+';\n';
alert(report);


/*  returned value: (String)
startword= teutonic
1 incorrect: nick;
19 correct: ton,on,out,tout,tone,tonic,tune,nice,note,
not,tot,tote,ice,tic,nick,cone,con,cut,cute;

*/