如何在字符串中找到第n个字符?

时间:2010-10-20 09:57:55

标签: java string substring

与发布here的问题类似,正在寻找 用于Java中的解决方案。

即,如何从字符串中找到第n次出现的字符/字符串的索引?

示例: / folder1 / folder2 / folder3 / ”。 在这种情况下,如果我要求第3次出现斜杠(/),它会出现在folder3之前,我希望返回这个索引位置。我的实际意图是从第n次出现的字符中对其进行子串。

Java API中是否有任何方便/现成的方法,或者我们是否需要自己编写一个小逻辑来解决这个问题?

另外,

  1. 我很快就在Apache Commons Lang StringUtils搜索了是否支持任何方法,但我找不到任何方法。
  2. 正则表达式在这方面有帮助吗?

20 个答案:

答案 0 :(得分:121)

如果您的项目已经依赖于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;
}

此帖子已被重写为文章here

答案 1 :(得分:55)

我认为找到第N个字符串的最简单的解决方案是使用Apache Commons的StringUtils.ordinalIndexOf()

示例:

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

答案 2 :(得分: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一样好,但可能更容易做对。

答案 3 :(得分: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;
    }
}

请注意,我在正则表达式中做了一些假设:

  • 输入路径是绝对的(即以“/”开头);
  • 结果中不需要第3个“/”。

根据评论中的要求,我会尝试解释正则表达式:(/[^/]*){2}/([^/]*)

Regular expression visualization

  • /[^/]*/后跟[^/]*(任意数量的字符不是/),
  • (/[^/]*)将前一个表达式分组到一个实体中。这是表达式的1 st组,
  • (/[^/]*){2}表示该群组必须与{2}次匹配,
  • [^/]*也是任意数量的不是/
  • 的字符
  • ([^/]*)将previos表达式分组到一个实体中。这是表达式的2组。

这样您只需获取与第二组匹配的子字符串:return m.group(2);

图片由Debuggex

提供

答案 4 :(得分: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;
}

答案 5 :(得分:5)

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

匹配任何后跟/两次,然后再次匹配。第三个是你想要的那个

Matcher状态可用于指出最后/是

的位置

答案 6 :(得分: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;
}

答案 7 :(得分:3)

现在支持Apache Commons Lang的StringUtils

这是原始的:

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

对于您的问题,您可以编写以下代码:StringUtils.ordinalIndexOf(uri, "/", 3)

您还可以使用lastOrdinalIndexOf方法在字符串中找到字符的最后第n次出现。

答案 8 :(得分: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);
}

答案 9 :(得分:2)

这个答案改进了@aioobe的回答。答案中的两个错误是固定的 1. n = 0应返回-1 2. nth occurence返回-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;
}

答案 10 :(得分: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;
        }
    }
}

答案 11 :(得分:1)

也许你可以通过String.split(..)方法实现这一点。

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

答案 12 :(得分: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;
}

答案 13 :(得分:0)

代码返回第n个出现位置substring又称字段宽度。例。如果字符串“Stack lowlow in low melow”是搜索第二出现令牌“low”的字符串,你会同意我第二次出现在子串“18和21”。 indexOfOccurance(“低溢出的堆栈溢出”,低,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));
    }
    }

答案 14 :(得分: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;
        }
    }
}

答案 15 :(得分: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;
}

答案 16 :(得分:0)

// scala

//如果该值第n次不存在,则抛出-1,即使该值直到第n-1次也存在。 //如果第n次出现该值,则抛出该索引

def indexOfWithNumber(tempString:String,valueString:String,numberOfOccurance:Int):Int={
var stabilizeIndex=0 
var tempSubString=tempString 
var tempIndex=tempString.indexOf(valueString) 
breakable
{
for ( i <- 1 to numberOfOccurance)
if ((tempSubString.indexOf(valueString) != -1) && (tempIndex != -1))
{
tempIndex=tempSubString.indexOf(valueString)
tempSubString=tempSubString.substring(tempIndex+1,tempSubString.size) // ADJUSTING FOR 0
stabilizeIndex=stabilizeIndex+tempIndex+1 // ADJUSTING FOR 0
}
else
{ 
stabilizeIndex= -1
tempIndex= 0
break
}
}
stabilizeIndex match { case value if value <= -1 => -1 case _ => stabilizeIndex-1 } // reverting for adjusting 0 previously
}


indexOfWithNumber("bbcfgtbgft","b",3) // 6
indexOfWithNumber("bbcfgtbgft","b",2) //1
indexOfWithNumber("bbcfgtbgft","b",4) //-1

indexOfWithNumber("bbcfgtbcgft","bc",1)  //1
indexOfWithNumber("bbcfgtbcgft","bc",4) //-1
indexOfWithNumber("bbcfgtbcgft","bc",2) //6

答案 17 :(得分:0)

APACHE 实现(复制粘贴:不要为一个函数导入整个库!)

这是从它们的 StringUtils 库中分离出来的确切 Apache Commons 实现(这样您就可以复制粘贴这个,而不必仅为一个函数添加库的依赖项):< /p>

/**
 * <p>Finds the n-th index within a String, handling {@code null}.
 * This method uses {@link String#indexOf(String)} if possible.</p>
 * <p>Note that matches may overlap<p>
 *
 * <p>A {@code null} CharSequence will return {@code -1}.</p>
 *
 * @param str  the CharSequence to check, may be null
 * @param searchStr  the CharSequence to find, may be null
 * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
 * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
 * @return the n-th index of the search CharSequence,
 *  {@code -1} if no match or {@code null} string input
 */
private static int ordinalIndexOf(final String str, final String searchStr, final int ordinal, final boolean lastIndex) {
    if (str == null || searchStr == null || ordinal <= 0) {
        return -1;
    }
    if (searchStr.length() == 0) {
        return lastIndex ? str.length() : 0;
    }
    int found = 0;
    // set the initial index beyond the end of the string
    // this is to allow for the initial index decrement/increment
    int index = lastIndex ? str.length() : -1;
    do {
        if (lastIndex) {
            index = str.lastIndexOf(searchStr, index - 1); // step backwards thru string
        } else {
            index = str.indexOf(searchStr, index + 1); // step forwards through string
        }
        if (index < 0) {
            return index;
        }
        found++;
    } while (found < ordinal);
    return index;
}

答案 18 :(得分:0)

看起来你想要子串的字符串是一个文件路径。你不能只用 / 分割然后从兴趣点开始使用数组条目吗?例如,

String folders = "/folder1/folder2/folder3/".split('/');
StringBuilder subStringed = new StringBuilder('/');
for (int i = 2; i < folders.length; i++) {
  subStringed.append(folders[i]).append('/').;
}
System.out.println(subStringed.toString());

答案 19 :(得分:0)

static int nthIndexOfChar(String str, int n, char ch) {
    int count = 0;
    for (int i = 0; i < str.length(); i++)
        if (str.charAt(i) ==  ch)
            if (++count == n)
                return i;
    return -1;
}