2010-10-20 216 views
74

與發佈的問題類似here,我正在尋找 以獲得Java解決方案。如何在字符串中找到第n個字符?

也就是說,如何從字符串中找到第n個字符/字符串出現的索引?

示例:/folder1中/文件夾2/folder3/」。 在這種情況下,如果我要求第3次出現斜槓(/),它會出現在folder3之前,並且我希望返回此索引位置。我的實際意圖是從第n個字符開始對它進行子串處理。

在Java API中是否有任何方便/可用的方法,或者我們是否需要自己編寫一個小邏輯來解決這個問題?

此外,

  1. 我快速地搜索任何方法是否支持此目的,在阿帕奇共享郎的StringUtils,但我沒有找到任何。
  2. 正則表達式在這方面可以提供幫助嗎?
+2

對於您的特定示例,根據您想要對結果執行的操作,將字符串拆分爲/可能會更容易,這可能會直接提供您所需的內容? – 2010-10-20 10:09:03

+0

@Paul:這也是個好主意。 – Gnanam 2010-10-20 11:33:39

回答

25

兩個簡單的選項出現:

  • 使用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,但它可能更容易得到正確。

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

匹配任何後跟/兩次,然後再次。第三個是你想

Matcher狀態可以用來指示從哪裏最後的/是

+0

我相信這是一個非常酷的答案,但是如何在我的代碼中使用它? – 2015-08-05 18:30:23

+0

看看@ andcoz的回答(不同的正則表達式,但想法是一樣的) – 2015-08-05 18:34:32

110

如果您的項目已經依賴於Apache的共享,你可以使用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; 
} 

該帖子已被改寫爲一篇文章here

+0

除了「off-by-one」錯誤之外,@Jon Skeet的解決方案還有另一個很大的好處 - 只需稍微調整一下(反轉循環) ,你也可以有「最後一次出現」。 – 2016-05-12 21:30:02

+0

@KaranChadha,同樣適用於此解決方案。只需轉到['lastIndexOf'](https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#lastIndexOf%28java.lang.String,%20int%29)。 – aioobe 2016-06-29 21:44:12

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

你可以嘗試這樣的事情:

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

Regular expression visualization

  • /[^/]*/其次[^/]*(即任何數目的字符不是/),
  • (/[^/]*) groups th e先前在單個實體中的表達。這是1第一組的表達的,
  • (/[^/]*){2}指該基團必須匹配您準確{2}倍,
  • [^/]*再次是不屬於/
  • ([^/]*)基團在所述previos表達的任何數量的字符單一實體。這是表達式的2第二組。

這種方式你只拿到了第2組相匹配的子字符串:return m.group(2);

圖片禮貌Debuggex

+1

你能用普通英語解釋正則表達式嗎?就像:一個反斜槓後面跟着不是無限期的背影......然後我不確定。 – Ced 2015-09-15 20:33:14

+1

@Ced,我給正則表達式添加了一個解釋和一個小的修復。我希望現在更清楚。 – andcoz 2015-09-17 11:39:03

+0

這很清楚,謝謝。 – Ced 2015-09-17 12:17:57

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

我相信最簡單的解決方案找到String的第N次出現是使用Apache Commons中的StringUtils.ordinalIndexOf()

例子:

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

我做了一些改動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; 
} 
+1

我認爲如果給出'null'作爲參數,該方法拋出NPE是合理的。這是標準庫中最常見的行爲。 – aioobe 2015-12-10 22:54:51

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

//純C++

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

如今有支撐的Apache的百科全書Lang的StringUtils

這是原始:

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

您的問題,您可以編寫以下:StringUtils.ordinalIndexOf(uri, "/", 3)

您還可以找到與lastOrdinalIndexOf方法的字符串的字符的最後第n次出現。

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

這個答案改善了@aioobe的答案。該答案中的兩個錯誤已修復。
1. n = 0應返回-1。
2.第n次出現返回-1,但它在第n次出現時起作用。

試試這個!

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; 
} 
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個發生位置串又名字段寬度。例。如果字符串「堆棧溢出在低melow」是要搜索的字符串第二個發生令牌「低」,你會同意我第二次發生在子字符串「18和21」。 indexOfOccurance(「在低melow中堆棧溢出」,低,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

也許你可以通過String.split(..)方法實現這一點。

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