2010-12-17 2 views
0

Ich möchte eine Regex-Matching-Funktion in Javascript implementieren, die mit einem oder mehreren Keywords in einem Text übereinstimmt. Jedes Schlüsselwort muss in beliebiger Reihenfolge gefunden werden. Schlüsselwörter werden vom Benutzer eingegeben.Regex Keyword-Matching

Hier ist, wo ich bin:

\b(smart.*\bwork.*|work.*\bsmart.*) 
  • Streichhölzer "trying to work smarter"
  • aber nicht "trying to work" or "trying to be smart"

Das Problem bei diesem Ansatz ist, ich verschiedene erstellen müssen Permutationen geordnet (so ähnlich sowieso) des Keyword-Sets.

So sind die Fragen:

  1. Wenn es eine einfache RegEx-einzige Weg? (Ie "\b(smart.*|work.*)<magic:all,anyorder>" was wird sicherstellen, dass alle Suchbegriffe gefunden werden, und in beliebiger Reihenfolge)
  2. Wenn nicht - Können Sie eine JavaScript-Implementierung von Array Permutationen (so dass aus [1,2,3] es erzeugt [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]])

UPDATE

Dies ist für die Suche nach einer Reihe von Zeichenfolgen (10-50 Zeichenfolgen) auf der Clientseite (im Browser) vorgesehen.

+4

Ich würde Regex nicht empfehlen, wenn es um "diese Schlüsselwörter in beliebiger Reihenfolge mit interlaced acceptables" geht. Ich würde 'indexOf()' für jedes Keyword empfehlen; es würde viel weniger kosten als die potentiell komplexe Regex. – BeemerGuy

+0

Es ist schwer zu verstehen, was Sie zu tun versuchen. Das ist nicht irgendein Spam-Randomizer, oder? –

+0

Ihre zweite Option klingt wie ein Performance-Albtraum, wenn Sie sie verwenden, um eine Reihe von RegExs zu generieren und sie alle zu testen. –

Antwort

5

Mein Freund Juan Antwort wird ziemlich gut funktionieren, es sei denn, der Benutzer ist für kleine Wörter suchen, die in größeren Wörter erscheinen. In diesem Fall müssen Sie auf reguläre Ausdrücke zurückgreifen. Sie können einen hybriden Ansatz verwenden, der nur den RE verwendet, wenn der String gefunden wird. Etwas wie:

String.prototype.containsAll = function(){ 
    for (var i=0; i < arguments.length; i++) { 

     if (this.indexOf(arguments[i]) > -1) { 
      // test with regular expressions 
      var re = new RegExp('\\b' + escapeRe(arguments[i]) + '\\b') 
      if (!re.test(this)) { 
       return false; 
      } 
     } else { 
      return false 
     } 
    } 
    return true; 

    function escapeRe(re) { 
     return re.replace(/[$.*+?()\[\]\\^]/g, function(chr) { 
      return '\\' + chr; 
     }); 
    } 
} 

Nie getestet, vor allem nicht das escapeRe Bit.

+1

Nicht schlecht! Ich habe es getestet und es funktioniert, aber nur, wenn alle Suchwort beginnt und endet mit einem Wortzeichen.Sie möchten vielleicht das führende '\\ b' durch' (?: \\ s | ^) 'und das nachfolgende mit' (?: \\ s | $) 'ersetzen.Aber nur das OP scheint sich um die führende Grenze zu kümmern .. Hier ist eine Demo, die auf dieser Annahme basiert: http://ideone.com/fZFzW –

+0

Woah, ich muss ein Lesezeichen bei ideone.com setzen! – Hemlock

1

Nur weil BeemerGuy es nicht als Antwort gepostet hat. Aber das Credo geht an ihn. Es gibt keine RegEx, die das tun kann, was Sie wollen. Es ist viel einfacher, eine Methode zu erstellen, die indexOf verwendet. Meine Leistungstests zeigen an, dass Sie indexOf nach Möglichkeit immer einem RegEx vorziehen sollten.

function containsAll(searchString /*, word, word,...*/) { 
    for (var i=1; i < arguments.length; i++) { 
    if (searchString.indexOf(arguments[i]) == -1) { 
     return false; 
    } 
    } 
    return true; 
} 

oder wenn Sie nichts dagegen nicht zu ändern String.prototype

String.prototype.containsAll = function(){ 
    for (var i=0; i < arguments.length; i++) { 
    if (this.indexOf(arguments[i]) == -1) { 
     return false; 
    } 
    } 
    return true; 
} 
+0

Sie meinen Namen falsch geschrieben = ( – BeemerGuy

+0

Dort es fest! – mkb

+0

Dank Matt, sorry BeemerGuy –