web-dev-qa-db-ger.com

Wie finde ich Indizes zu allen Vorkommen einer Zeichenfolge in einer anderen in JavaScript?

Ich versuche, die Positionen aller Vorkommen einer Zeichenfolge in einer anderen Zeichenfolge zu finden, ohne Berücksichtigung der Groß- und Kleinschreibung.

Zum Beispiel die Zeichenfolge gegeben:

le, möchte ich das Array erhalten:

[2, 25, 27, 33]

Beide Zeichenketten sind Variablen, d. H. Ich kann ihre Werte nicht hart codieren.

Ich dachte, dies sei eine einfache Aufgabe für reguläre Ausdrücke, aber nachdem ich eine Weile versucht hatte, eine zu finden, die funktionieren würde, hatte ich kein Glück.

Ich habe dieses Beispiel gefunden, wie man dies mit .indexOf() bewerkstelligt, aber es muss doch ein knapperer Weg dafür sein?

65
Bungle
var str = "I learned to play the Ukulele in Lebanon."
var regex = /le/gi, result, indices = [];
while ( (result = regex.exec(str)) ) {
    indices.Push(result.index);
}

UPDATE

Ich habe in der ursprünglichen Frage nicht festgestellt, dass die Suchzeichenfolge eine Variable sein muss. Ich habe eine andere Version geschrieben, die sich mit diesem Fall befasst, der indexOf verwendet. Wie Wrikken in den Kommentaren darauf hingewiesen hat, müsste man für den allgemeinen Fall mit regulären Ausdrücken spezielle Regex-Zeichen umgehen, wobei die Regex-Lösung meiner Meinung nach mehr Kopfschmerzen als wertvoll ist.

function getIndicesOf(searchStr, str, caseSensitive) {
    var searchStrLen = searchStr.length;
    if (searchStrLen == 0) {
        return [];
    }
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.Push(index);
        startIndex = index + searchStrLen;
    }
    return indices;
}

var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");

document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>

123
Tim Down

Hier ist Regex freie Version:

function indexes(source, find) {
  if (!source) {
    return [];
  }
  // if find is empty string return all indexes.
  if (!find) {
    // or shorter arrow function:
    // return source.split('').map((_,i) => i);
    return source.split('').map(function(_, i) { return i; });
  }
  var result = [];
  for (i = 0; i < source.length; ++i) {
    // If you want to search case insensitive use 
    // if (source.substring(i, i + find.length).toLowerCase() == find) {
    if (source.substring(i, i + find.length) == find) {
      result.Push(i);
    }
  }
  return result;
}

indexes("I learned to play the Ukulele in Lebanon.", "le")

EDIT: und wenn Sie Zeichenfolgen wie 'aaaa' und 'aa' suchen möchten, um [0, 2] zu finden, verwenden Sie diese Version:

function indexes(source, find) {
  if (!source) {
    return [];
  }
  if (!find) {
      return source.split('').map(function(_, i) { return i; });
  }
  var result = [];
  var i = 0;
  while(i < source.length) {
    if (source.substring(i, i + find.length) == find) {
      result.Push(i);
      i += find.length;
    } else {
      i++;
    }
  }
  return result;
}
13
jcubic

Sie können das sicher tun!

//make a regular expression out of your needle
var needle = 'le'
var re = new RegExp(needle,'gi');
var haystack = 'I learned to play the Ukulele';

var results = new Array();//this is the results you want
while (re.exec(haystack)){
  results.Push(re.lastIndex);
}

Edit: Erlernen von RegExp

Außerdem wurde mir klar, dass dies nicht genau ist, was Sie wollen, da lastIndex uns sagt, dass das Ende der Nadel nicht der Anfang ist, aber es ist nahe - Sie könnten re.lastIndex-needle.length in das Ergebnisarray drücken ...

Bearbeiten: Link hinzufügen

Die Antwort von @Tim Down verwendet das Ergebnisobjekt von RegExp.exec (), und alle meine Javascript-Ressourcen beschränken sich auf deren Verwendung (abgesehen von der Angabe der übereinstimmenden Zeichenfolge). Wenn er result.index verwendet, ist dies eine Art unbenanntes Match-Objekt. In der MDC-Beschreibung von exec beschreiben sie dieses Objekt tatsächlich in anständigen Details.

11
Ryley

Wenn Sie nur die Position aller Spiele finden möchten, möchte ich Sie auf einen kleinen Hack verweisen:

haystack = 'I learned to play the Ukulele in Lebanon.'
needle = 'le'
splitOnFound = haystack.split(needle).map(function (culm) {
  return this.pos += culm.length + needle.length
}, {pos: -needle.length}).slice(0, -1)

es ist möglicherweise nicht hilfreich, wenn Sie ein RegExp mit variabler Länge haben, aber für einige kann es hilfreich sein.

2
Hoffmann

Verwenden Sie String.prototype.match .

Hier ist ein Beispiel aus den MDN-Dokumenten selbst:

var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);

console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
0
tejasbubane

Folgen Sie der Antwort von @jcubic, seine Lösung hat zu einem kleinen Durcheinander für meinen Fall geführt
Zum Beispiel var result = indexes('aaaa', 'aa') wird [0, 1, 2] anstelle von [0, 2] zurückgegeben. 
Also habe ich seine Lösung ein wenig aktualisiert, um zu meinem Fall zu passen

function indexes(text, subText, caseSensitive) {
    var _source = text;
    var _find = subText;
    if (caseSensitive != true) {
        _source = _source.toLowerCase();
        _find = _find.toLowerCase();
    }
    var result = [];
    for (var i = 0; i < _source.length;) {
        if (_source.substring(i, i + _find.length) == _find) {
            result.Push(i);
            i += _find.length;  // found a subText, skip to next position
        } else {
            i += 1;
        }
    }
    return result;
}
0

Hier ist ein einfacher Code 

function getIndexOfSubStr(str, serchToken, preIndex, output){
		 var result = str.match(serchToken);
     if(result){
     output.Push(result.index +preIndex);
     str=str.substring(result.index+serchToken.length);
     getIndexOfSubStr(str, serchToken, preIndex, output)
     }
     return output;
  };

var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var  serchToken ="my";
var preIndex = 0;

console.log(getIndexOfSubStr(str, serchToken, preIndex, []));

0
Kapil Tiwari

Vielen Dank für alle Antworten. Ich habe sie alle durchgesehen und eine Funktion gefunden, die dem ersten einen letzten Index jedes Vorkommens der 'Nadel'-Teilzeichenfolge gibt. Ich poste es hier, falls es jemandem hilft.

Bitte beachten Sie, dass dies nicht mit der ursprünglichen Anforderung nur für den Beginn jedes Auftretens identisch ist. Es passt besser zu meinem Verwendungszweck, da Sie die Nadellänge nicht einhalten müssen.

function findRegexIndices(text, needle, caseSensitive){
  var needleLen = needle.length,
    reg = new RegExp(needle, caseSensitive ? 'gi' : 'g'),
    indices = [],
    result;

  while ( (result = reg.exec(text)) ) {
    indices.Push([result.index, result.index + needleLen]);
  }
  return indices
}
0
Roei Bahumi