Как найти n-ое появление символа в строке?
Как и в опубликованном вопросе здесь, я смотрю
для решения в Java.
То есть, как найти индекс n-го вхождения символа/строки из строки?
Пример: "/folder1/folder2/folder3/".
В этом случае, если я запрашиваю 3-е вхождение косой черты (/), оно появляется перед папкой 3, и я ожидаю вернуть эту позицию индекса. Мое фактическое намерение состоит в том, чтобы подстроить его из n-го вхождения символа.
Есть ли удобный/готовый к использованию метод, доступный в Java API, или нам нужно написать небольшую логику для решения этой проблемы?
Кроме того,
- Я быстро искал, поддерживается ли какой-либо метод для этой цели в Apache Commons Lang StringUtils, но я не нашел.
- Помогают ли регулярные выражения в этом отношении?
Ответы
Ответ 1
Если ваш проект уже зависит от Apache Commons, вы можете использовать StringUtils.ordinalIndexOf
, в противном случае здесь реализована реализация:
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;
}
Это сообщение было переписано как статья здесь.
Ответ 2
Я считаю, что самым простым решением для поиска N-го вхождения String является использование StringUtils.ordinalIndexOf() из Apache Commons.
Пример:
StringUtils.ordinalIndexOf("aabaabaa", "b", 2) == 5
Ответ 3
Возможны два простых варианта:
- Повторно используйте
charAt()
- Повторно используйте
indexOf()
Например:
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;
}
Это может не работать так же, как с помощью indexOf
несколько раз, но, возможно, проще получить право.
Ответ 4
Вы можете попробовать что-то вроде этого:
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;
}
}
Обратите внимание, что я сделал некоторые предположения в регулярном выражении:
- входной путь является абсолютным (т.е. начинается с "/" );
- вам не понадобится 3-й "/" в результате.
Как указано в комментарии, я попытаюсь объяснить регулярное выражение: (/[^/]*){2}/([^/]*)
![Regular expression visualization]()
-
/[^/]*
- это /
, за которым следует [^/]*
(любое количество символов, которые не являются /
),
-
(/[^/]*)
группирует предыдущее выражение в одном объекте. Это 1
st-группа выражения,
-
(/[^/]*){2}
означает, что группа должна соответствовать {2}
раз,
-
[^/]*
- это снова любое количество символов, которые не являются /
,
-
([^/]*)
группирует выражение previos в одном объекте. Это 2
nd группа выражения.
Таким образом, вы должны получить только подстроку, которая соответствует второй группе: return m.group(2);
Изображение предоставлено Debuggex
Ответ 5
Я сделал несколько изменений в ответе aioobe и получил n-ю версию lastIndexOf и исправил некоторые проблемы с NPE. См. Следующий код:
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;
}
Ответ 6
([.^/]*/){2}[^/]*(/)
Сопоставьте все, за чем следует/два раза, затем снова. Третий - тот, который вы хотите
Состояние Matcher может использоваться, чтобы указать, где находится последний/
Ответ 7
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;
}
Ответ 8
В настоящее время существует поддержка Apache Commons Lang StringUtils,
Это примитив:
int org.apache.commons.lang.StringUtils.ordinalIndexOf(CharSequence str, CharSequence searchStr, int ordinal)
для вашей проблемы вы можете закодировать следующее: StringUtils.ordinalIndexOf(uri, "/", 3)
Вы также можете найти последнее n-ое вхождение символа в строке с помощью метода lastOrdinalIndexOf.
Ответ 9
Другой подход:
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);
}
Ответ 10
Этот ответ улучшает ответ @aioobe. Две ошибки в этом ответе были исправлены.
1. n = 0 должен возвращать -1.
2. n-е появление возвращено -1, но оно работало на n-1 вхождениях.
Попробуйте это!
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;
}
Ответ 11
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;
}
}
}
Ответ 12
/* 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;i<c.length;i++)
{
if(c[i]==key)
{
count++;
position=i;
if(count==n)
{
System.out.println("Character found");
System.out.println("the position at which the " + count + " ocurrence occurs is " + position);
return;
}
}
}
if(n>count)
{
System.out.println("Character occurs "+ count + " times");
return;
}
}
}
Ответ 13
Мое решение:
/**
* Like String.indexOf, but find the n:th occurance of c
* @param s string to search
* @param c character to search for
* @param n n: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;
}
Ответ 14
Код возвращает n-ю позицию позиции substring aka ширину поля. Пример. если строка "Переполнение стека в нижней части" - это строка для поиска 2nd возникновения токена "низкий", вы согласитесь со мной в том, что это второе событие при подстановке "18 и 21" . indexOfOccurance ( "Переполнение стека в low melow", low, 2) возвращает 18 и 21 в строке.
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));
}
}
Ответ 15
Возможно, вы могли бы достичь этого и с помощью метода String.split(..).
String str = "";
String[] tokens = str.split("/")
return tokens[nthIndex] == null
Ответ 16
//в чистом С++
int pos = 0;
for ( int i = 0; i < N; ++i ) // N = nth position
{
pos = STRING.find( delim, pos + size_of_delim );
}