문자열에서 n 번째 문자를 찾는 방법은 무엇입니까?


95

여기 에 게시 된 질문과 유사하게 Java로 솔루션을 찾고 있습니다.

즉, 문자열에서 문자 / 문자열의 n 번째 발생 인덱스를 찾는 방법은 무엇입니까?

예 : " / folder1 / folder2 / folder3 / ". 이 경우 세 번째 슬래시 (/)를 요청하면 folder3 앞에 나타나며이 인덱스 위치를 반환 할 것으로 예상합니다. 내 실제 의도는 문자의 n 번째 발생에서 부분 문자열을 만드는 것입니다.

Java API에서 사용할 수있는 편리하고 즉시 사용할 수있는 방법이 있습니까? 아니면이 문제를 해결하기 위해 자체적으로 작은 논리를 작성해야합니까?

또한,

  1. Apache Commons Lang의 StringUtils 에서 이러한 목적으로 지원되는 방법이 있는지 빠르게 검색 했지만 찾을 수 없습니다.
  2. 이와 관련하여 정규 표현식이 도움이 될 수 있습니까?

2
특정 예의 경우 결과로 수행하려는 작업에 따라 문자열을 /로 분할하는 것이 더 쉬울 수 있습니다. 그러면 직접 필요한 것을 얻을 수 있습니까?
The Archetypal Paul

@Paul : 그것도 좋은 생각입니다.
Gnanam

답변:


128

프로젝트가 이미 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;
}

이 게시물은 여기 에 기사로 다시 작성되었습니다 .


"off-by-one"오류를 제외하고 @Jon Skeet의 솔루션에는 또 다른 큰 긍정적 인 점이 있습니다.-사소한 조정 (루프 반전)으로 "마지막에서 n 번째 발생"을 가질 수도 있습니다.
Karan Chadha

@KaranChadha,이 솔루션에도 동일하게 적용됩니다. 로 변경하십시오 lastIndexOf.
aioobe


27

두 가지 간단한 옵션이 발생합니다.

  • 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반복적 으로 사용하는 것만 큼 성능이 좋지 않을 수 있지만 올바르게 사용 하는 것이 더 간단 할 수 있습니다.


15

다음과 같이 시도 할 수 있습니다.

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

정규식에서 몇 가지 가정을 수행했습니다.

  • 입력 경로는 절대적입니다 (예 : "/"로 시작).
  • 결과에 세 번째 "/"가 필요하지 않습니다.

의견에서 요청한대로 정규식을 설명하려고합니다. (/[^/]*){2}/([^/]*)

정규식 시각화

  • /[^/]*A는 /다음 [^/]*의 (a하지 않은 문자의 수 /)
  • (/[^/]*)이전 표현식을 단일 항목으로 그룹화합니다. 이것은 1표현식 의 st 그룹입니다.
  • (/[^/]*){2}그룹이 정확히 {2}시간 과 일치해야 함을 의미합니다.
  • [^/]*다시 말하지만 /,
  • ([^/]*)previos 표현식을 단일 엔티티로 그룹화합니다. 이것은 2표현식 의 두 번째 그룹입니다.

이렇게하면 두 번째 그룹과 일치하는 부분 문자열 만 가져 오면됩니다. return m.group(2);

이미지 제공 : Debuggex


1
일반 영어로 정규식을 설명해 주시겠습니까? Like : 백 슬래시 뒤에 백 슬래시가 아닌 것은 무한한 횟수 ... 그럼 나는 확실하지 않습니다.
Ced

1
@Ced, 정규식에 대한 설명과 작은 수정 사항을 추가했습니다. 이제 더 명확 해 졌으면합니다.
andcoz 2015 년

정규식을 설명해 주셔서 감사합니다.
Vishwa Ratna

8

aioobe의 답변을 몇 가지 변경하고 nth 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;
}

3
null인수로 주어지면 메서드가 NPE를 던지는 것이 합리적이라고 생각합니다 . 이것은 표준 라이브러리에서 가장 일반적인 동작입니다.
aioobe 2015

5
 ([.^/]*/){2}[^/]*(/)

/ 두 번 뒤에 오는 모든 항목을 일치시킨 다음 다시 일치시킵니다. 세 번째는 당신이 원하는 것입니다

매처 / 마지막이고 상태는 말할 수 있습니다


이것은 매우 멋진 대답이라고 확신하지만 코드에서 어떻게 사용합니까?
ARK

@ andcoz의 대답에서 봐 (다른 정규 표현식,하지만 아이디어는 동일)
전형적인 폴

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

3

요즘에는 Apache Commons Lang의 StringUtils 지원이 있습니다 .

이것은 기본입니다.

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

문제에 대해 다음을 코딩 할 수 있습니다. StringUtils.ordinalIndexOf(uri, "/", 3)

lastOrdinalIndexOf 메서드를 사용하여 문자열에서 마지막 n 번째 문자를 찾을 수도 있습니다 .


3

String.split (..) 메서드를 통해서도이 작업을 수행 할 수 있습니다.

String str = "";
String[] tokens = str.split("/")
return tokens[nthIndex] == null 

2

또 다른 접근 방식 :

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

2

이 답변은 @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;
}

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

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

0

내 솔루션 :

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

0

코드는 필드 너비라고도하는 n 번째 발생 위치 하위 문자열을 반환합니다. 예. 문자열 "Stack overflow in low melow" 가 "low"토큰의 두 번째 발생 을 검색하는 문자열 인 경우 두 번째 발생이 "18 and 21" 서브 트링에 있음에 동의합니다 . indexOfOccurance ( "Stack overflow in 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));
    }
    }

0
public static int findNthOccurrence(String phrase, String str, int n)
{
    int val = 0, loc = -1;
    for(int i = 0; i <= phrase.length()-str.length() && val < n; i++)
    {
        if(str.equals(phrase.substring(i,i+str.length())))
        {
            val++;
            loc = i;
        }
    }

    if(val == n)
        return loc;
    else
        return -1;
}

2
이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 아마도 더 많은 찬성 투표를 받게됩니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 답변을 수정하여 설명을 추가하고 적용되는 제한 및 가정에 대한 표시를 제공하십시오.
고래의 마법사 피카
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.