¿Cómo encontrar enésima ocurrencia de carácter en una cadena?

Similar a una pregunta publicada aquí , estoy buscando una solución en Java.

Es decir, ¿cómo encontrar el índice de n-ésima ocurrencia de un carácter / cadena de una cadena?

Ejemplo:/ carpeta1 / carpeta2 / carpeta3 / “. En este caso, si solicito la 3ra aparición de barra (/), aparece antes de la carpeta 3, y espero devolver esta posición de índice. Mi intención real es subscribirlo desde la enésima ocurrencia de un personaje.

¿Hay algún método conveniente / listo para usar disponible en la API de Java o necesitamos escribir una pequeña lógica por nuestra cuenta para resolver esto?

También,

  1. Rápidamente busqué si algún método es compatible con este propósito en StringUtils de Apache Commons Lang, pero no encuentro ninguno.
  2. ¿Pueden las expresiones regulares ayudar en este sentido?

Si su proyecto ya depende de Apache Commons, puede usar StringUtils.ordinalIndexOf , de lo contrario, aquí hay una implementación:

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

Esta publicación ha sido reescrita como un artículo aquí .

Creo que la solución más fácil para encontrar la enésima aparición de una Cadena es usar StringUtils.ordinalIndexOf () de Apache Commons.

Ejemplo:

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

Dos opciones simples ocurren:

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

Por ejemplo:

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

Puede que no funcione tan bien como usar indexOf repetidamente, pero posiblemente sea más sencillo hacerlo bien.

Puedes probar algo como esto:

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

Tenga en cuenta que hice algunas suposiciones en la expresión regular:

  • la ruta de entrada es absoluta (es decir, comienza con “/”);
  • no necesita el 3er “/” en el resultado.

Como solicité en un comentario, intentaré explicar la expresión regular: (/[^/]*){2}/([^/]*)

Visualización de expresión regular

  • /[^/]* es a / seguido de [^/]* (cualquier cantidad de caracteres que no sean a / ),
  • (/[^/]*) agrupa la expresión anterior en una sola entidad. Este es el primer grupo de la expresión,
  • (/[^/]*){2} significa que el grupo debe coincidir extactamente {2} veces,
  • [^/]* es de nuevo cualquier número de caracteres que no sean a / ,
  • ([^/]*) agrupa la expresión anterior en una sola entidad. Este es el 2º grupo de la expresión.

De esta forma, solo tiene que obtener la subcadena que coincide con el segundo grupo: return m.group(2);

Imagen cortesía de Debuggex

Hice algunos cambios a la respuesta de aioobe y obtuve una enésima versión de LastIndexOf, y solucioné algunos problemas de NPE. Vea el código a continuación:

 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}[^/]*(/) 

Empareja todo seguido de / dos veces, luego otra vez. El tercero es el que quieres

El estado de Matcher se puede usar para indicar dónde está el ú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; } 

Hoy en día hay soporte para StringUtils de Apache Commons Lang,

Este es el primitivo:

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

para su problema puede codificar lo siguiente: StringUtils.ordinalIndexOf(uri, "/", 3)

También puede encontrar la última n. ° aparición de un carácter en una cadena con el último método OrdinalIndexOf .

Otro enfoque:

 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 respuesta mejora con la respuesta de @aioobe. Se corrigieron dos errores en esa respuesta.
1. n = 0 debería devolver -1.
2. nth occurrence devolvió -1, pero funcionó en n-1th ocurrencias.

Prueba esto !

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

Puede ser que puedas lograr esto a través del método String.split (..) también.

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

Mi solución:

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

El código devuelve la enésima posición de la subcadena de posiciones aka ancho de campo. Ejemplo. si la cadena “desbordamiento de la stack en melodía baja” es la cadena para buscar la segunda ocurrencia de la ficha “baja”, estarás de acuerdo conmigo en que la segunda ocurrencia está en la subcadena “18 y 21” . indexOfOccurance (“Desbordamiento de stack en baja melow”, baja, 2) devuelve 18 y 21 en una cadena.

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

// en puro c ++

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