Pergunta

Eu estou tentando encontrar as posições de todas as ocorrências de uma string em outra seqüência, não diferencia maiúsculas de minúsculas.

Por exemplo, dada a seqüência de caracteres:

I learned to play the Ukulele in Lebanon.

e a cadeia de caracteres de pesquisa le, Eu quero obter a matriz:

[2, 25, 27, 33]

Ambas as cadeias serão variáveis - por exemplo, eu não posso codificar seus valores.

Eu percebi que esta era uma tarefa fácil para expressões regulares, mas depois de lutar durante um tempo para encontrar um que poderia funcionar, eu não tive nenhuma sorte.

Eu encontrei este exemplo de como fazer isso usando .indexOf(), mas certamente que tem de ser mais clara forma de o fazer?

Foi útil?

Solução

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);
}

ATUALIZAÇÃO

Não conseguiu detectar em questão original que a cadeia de caracteres de pesquisa precisa ser uma variável.Eu escrevi uma outra versão para lidar com este caso que utiliza indexOf, então você está de volta para onde você começou.Como apontado por Wrikken nos comentários, para fazer isso para o caso geral com expressões regulares, você precisará escapar especial regex caracteres, em que ponto eu acho que a regex solução torna-se mais uma dor de cabeça que não vale a pena.

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>

Outras dicas

Aqui é regex versão gratuita:

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")

EDITAR:e se você deseja fazer a correspondência de cadeias de caracteres como 'aaaa' e 'aa' para encontrar [0, 2] use esta versão:

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;
}

Com certeza você pode fazer isso!

//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);
}

Editar:aprender a soletrar RegExp

Além disso, eu percebi que este não é exatamente o que você quer, como lastIndex diz-nos a ponta da agulha não é o início, mas de perto você pode empurrar re.lastIndex-needle.length nos resultados da matriz...

Editar:adicionar link

@Tim de Down resposta utiliza os resultados de objeto RegExp.exec(), e todos os meus recursos Javascript gloss por cima do seu uso (além de dar-lhe a seqüência correspondente).Então, quando ele usa result.index, que algum tipo de unnamed Objeto de Correspondência.No MDC descrição de exec, na verdade, eles descrevem este objecto digno de detalhe.

Se você só quer encontrar a posição de todos os jogos que eu gostaria de apontar-lhe um pouco de hack:

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)

ele pode não ser applikable se você tem uma RegExp com comprimento variável, mas para alguns pode ser útil.

Utilização Seqüência de caracteres.protótipo.partida.

Aqui está um exemplo do MDN docs em si:

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']

Siga a resposta de @jcubic, sua solução provocou uma pequena confundir para o meu caso
Por exemplo var result = indexes('aaaa', 'aa') ele vai voltar [0, 1, 2] em vez de [0, 2]
Então eu atualizei um pouco a sua solução abaixo para coincidir com o meu caso

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;
}

Aqui está um Código simples

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, []));

Obrigado por todas as respostas.Eu passei por todos eles, e veio com uma função que dá o primeiro um último índice de cada ocorrência de 'agulha' subseqüência de caracteres .Estou postando aqui no caso, ele vai ajudar alguém.

Por favor, note que não é o mesmo que o pedido original apenas para o início de cada ocorrência.Ele combina com o meu caso de uso melhor, pois você não precisa manter o comprimento da agulha.

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
}

o código abaixo irá fazer o trabalho para você :

function indexes(source, find) {
  var result = [];
  for(i=0;i<str.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("hello, how are you", "ar")
function countInString(searchFor,searchIn){

 var results=0;
 var a=searchIn.indexOf(searchFor)

 while(a!=-1){
   searchIn=searchIn.slice(a*1+searchFor.length);
   results++;
   a=searchIn.indexOf(searchFor);
 }

return results;

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top