Como encontrar a nth ocorrência de caracteres em uma string?

Semelhante a uma pergunta postada aqui , estou procurando uma solução em Java.

Isto é, como encontrar o índice da nth ocorrência de um caractere / string de uma string?

Exemplo:/ folder1 / folder2 / folder3 / “. Nesse caso, se eu solicitar a terceira ocorrência de barra (/), ela aparecerá antes de folder3 e espero retornar essa posição de índice. Minha intenção real é substring-lo de enésima ocorrência de um personagem.

Existe algum método conveniente / pronto para uso disponível na API Java ou precisamos escrever uma pequena lógica por conta própria para resolver isso?

Além disso,

  1. Eu rapidamente procurei se algum método é suportado para esse propósito no StringUtils do Apache Commons Lang, mas não encontro nenhum.
  2. As expressões regulares podem ajudar nesse sentido?

    Se o seu projeto já depende do Apache Commons, você pode usar StringUtils.ordinalIndexOf , caso contrário, aqui está uma implementação:

     public static int ordinalIndexOf(String str, String substr, int n) { int pos = str.indexOf(substr); while (--n > 0 && pos != -1) pos = str.indexOf(substr, pos + 1); return pos; } 

    Este post foi reescrito como um artigo aqui .

    Eu acredito que a solução mais fácil para encontrar a enésima ocorrência de uma String é usar StringUtils.ordinalIndexOf () do Apache Commons.

    Exemplo:

     StringUtils.ordinalIndexOf("aabaabaa", "b", 2) == 5 

    Duas opções simples ocorrem:

    • Use charAt() repetidamente
    • Use indexOf() repetidamente

    Por exemplo:

     public static int nthIndexOf(String text, char needle, int n) { for (int i = 0; i < text.length(); i++) { if (text.charAt(i) == needle) { n--; if (n == 0) { return i; } } } return -1; } 

    Isso pode não funcionar tão bem quanto usar indexOf repetidamente, mas é possivelmente mais simples acertar.

    Você pode tentar algo assim:

     import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { System.out.println(from3rd("/folder1/folder2/folder3/")); } private static Pattern p = Pattern.compile("(/[^/]*){2}/([^/]*)"); public static String from3rd(String in) { Matcher m = p.matcher(in); if (m.matches()) return m.group(2); else return null; } } 

    Note que eu fiz algumas suposições no regex:

    • o caminho de input é absoluto (isto é, começa com “/”);
    • você não precisa do terceiro “/” no resultado.

    Como solicitado em um comentário, tentarei explicar o regex: (/[^/]*){2}/([^/]*)

    Visualização de expressão regular

    • /[^/]* é um / seguido por [^/]* (qualquer número de caracteres que não sejam / ),
    • (/[^/]*) agrupa a expressão anterior em uma única entidade. Este é o 1 grupo da expressão,
    • (/[^/]*){2} significa que o grupo deve coincidir com {2} vezes,
    • [^/]* é novamente qualquer número de caracteres que não são / ,
    • ([^/]*) agrupa a expressão previos em uma única entidade. Este é o 2 grupo da expressão.

    Desta forma, você só tem que obter a substring que corresponde ao segundo grupo: return m.group(2);

    Imagem cortesia de Debuggex

    Fiz algumas alterações na resposta do aioobe e obtive uma enésima versão lastIndexOf e corrigi alguns problemas do NPE. Veja o código abaixo:

     public int nthLastIndexOf(String str, char c, int n) { if (str == null || n < 1) return -1; int pos = str.length(); while (n-- > 0 && pos != -1) pos = str.lastIndexOf(c, pos - 1); return pos; } 
      ([.^/]*/){2}[^/]*(/) 

    Combine qualquer coisa seguida por / duas vezes e, em seguida, novamente. O terceiro é aquele que você quer

    O estado do Matcher pode ser usado para dizer onde o último / é

     public static int nth(String source, String pattern, int n) { int i = 0, pos = 0, tpos = 0; while (i < n) { pos = source.indexOf(pattern); if (pos > -1) { source = source.substring(pos+1); tpos += pos+1; i++; } else { return -1; } } return tpos - 1; } 

    Atualmente existe suporte para o StringUtils do Apache Commons Lang,

    Este é o primitivo:

     int org.apache.commons.lang.StringUtils.ordinalIndexOf(CharSequence str, CharSequence searchStr, int ordinal) 

    Para o seu problema, você pode codificar o seguinte: StringUtils.ordinalIndexOf(uri, "/", 3)

    Você também pode encontrar a última n-ésima ocorrência de um caractere em uma string com o método lastOrdinalIndexOf .

    Outra abordagem:

     public static void main(String[] args) { String str = "/folder1/folder2/folder3/"; int index = nthOccurrence(str, '/', 3); System.out.println(index); } public static int nthOccurrence(String s, char c, int occurrence) { return nthOccurrence(s, 0, c, 0, occurrence); } public static int nthOccurrence(String s, int from, char c, int curr, int expected) { final int index = s.indexOf(c, from); if(index == -1) return -1; return (curr + 1 == expected) ? index : nthOccurrence(s, index + 1, c, curr + 1, expected); } 

    Esta resposta melhora a resposta do @aioobe. Dois erros nessa resposta foram corrigidos.
    1. n = 0 deve retornar -1.
    2. a nth ocorrência retornou -1, mas trabalhou em n-1th ocorrências.

    Tente isso!

      public int nthOccurrence(String str, char c, int n) { if(n < = 0){ return -1; } int pos = str.indexOf(c, 0); while (n-- > 1 && pos != -1) pos = str.indexOf(c, pos+1); return pos; } 
     public class Sam_Stringnth { public static void main(String[] args) { String str="abcabcabc"; int n = nthsearch(str, 'c', 3); if(n< =0) System.out.println("Character not found"); else System.out.println("Position is:"+n); } public static int nthsearch(String str, char ch, int n){ int pos=0; if(n!=0){ for(int i=1; i<=n;i++){ pos = str.indexOf(ch, pos)+1; } return pos; } else{ return 0; } } } 

    Pode ser que você possa conseguir isso através do método String.split (..) também.

     String str = ""; String[] tokens = str.split("/") return tokens[nthIndex] == null 
     /* program to find nth occurence of a character */ import java.util.Scanner; public class CharOccur1 { public static void main(String arg[]) { Scanner scr=new Scanner(System.in); int position=-1,count=0; System.out.println("enter the string"); String str=scr.nextLine(); System.out.println("enter the nth occurence of the character"); int n=Integer.parseInt(scr.next()); int leng=str.length(); char c[]=new char[leng]; System.out.println("Enter the character to find"); char key=scr.next().charAt(0); c=str.toCharArray(); for(int i=0;icount) { System.out.println("Character occurs "+ count + " times"); return; } } } 

    Minha solução:

     /** * Like String.indexOf, but find the n:th occurance of c * @param s string to search * @param c character to search for * @param nn:th character to seach for, starting with 1 * @return the position (0-based) of the found char, or -1 if failed */ public static int nthIndexOf(String s, char c, int n) { int i = -1; while (n-- > 0) { i = s.indexOf(c, i + 1); if (i == -1) break; } return i; } 

    O código retorna a n-ésima posição das ocorrências, substring aka largura do campo. Exemplo. Se a string “Stack overflow in low melow” for a string para pesquisar a segunda ocorrência de token “low”, você concordará comigo que a segunda ocorrência está em subtração “18 and 21” . indexOfOccurance (“Stack overflow in low melow”, low, 2) retorna 18 e 21 em uma string.

     class Example{ public Example(){ } public String indexOfOccurance(String string, String token, int nthOccurance) { int lengthOfToken = token.length(); int nthCount = 0; for (int shift = 0,count = 0; count < string.length() - token.length() + 2; count++, shift++, lengthOfToken++) if (string.substring(shift, lengthOfToken).equalsIgnoreCase(token)) { // keeps count of nthOccurance nthCount++; if (nthCount == nthOccurance){ //checks if nthCount == nthOccurance. If true, then breaks return String.valueOf(shift)+ " " +String.valueOf(lengthOfToken); } } return "-1"; } public static void main(String args[]){ Example example = new Example(); String string = "the man, the woman and the child"; int nthPositionOfThe = 3; System.out.println("3rd Occurance of the is at " + example.indexOfOccurance(string, "the", nthPositionOfThe)); } } 

    // em c ++ puro

     int pos = 0; for ( int i = 0; i < N; ++i ) // N = nth position { pos = STRING.find( delim, pos + size_of_delim ); }