关于java:如何查找字符串中字符的第n个出现?

How to find nth occurrence of character in a string?

与此处发布的问题类似,正在寻找
Java解决方案。

也就是说,如何从字符串中找到第n个出现的字符/字符串的索引?

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

Java API中是否有任何方便/易于使用的方法,还是我们需要自己编写一个小的逻辑来解决这个问题?

也,

  • 我迅速在Apache Commons Lang的StringUtils中搜索是否为此目的支持任何方法,但找不到任何方法。
  • 正则表达式可以在这方面有所帮助吗?

  • 如果您的项目已经依赖于Apache Commons,则可以使用StringUtils.ordinalIndexOf,否则,这里是一个实现:

    1
    2
    3
    4
    5
    6
    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;
    }

    这篇文章在这里已被重写为文章。


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

    例:

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

    发生两个简单的选择:

    • 重复使用charAt()
    • 重复使用indexOf()

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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那样好,但是正确起来可能更简单。


    您可以尝试如下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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

    • /[^/]*/,后跟[^/]*(不是/的任意数量的字符),
    • (/[^/]*)将先前的表达式归为一个实体。这是表达式的第x10组,
    • (/[^/]*){2}表示该组必须完全匹配{2}次,
    • [^/]*同样是任意数量的不是/的字符,
    • ([^/]*)将previos表达式分组在一个实体中。这是表达式的2组。

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

    图片由Debuggex提供


    我对aioobe的答案进行了一些更改,并获得了第n个lastIndexOf版本,并修复了一些NPE问题。参见下面的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    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
     ([.^/]*/){2}[^/]*(/)

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

    Matcher状态可以用来告诉最后一个/在哪里


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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;
    }

    如今,已经支持Apache Commons Lang的StringUtils,

    这是原始的:

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

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

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


    可能您也可以通过String.split(..)方法实现此目的。

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

    此答案在@aioobe的答案上有所改进。该错误的两个错误是固定的。
    1. n = 0应该返回-1。
    2.第n个事件返回-1,但它在第n-1个事件中起作用。

    尝试这个 !

    1
    2
    3
    4
    5
    6
    7
    8
    9
        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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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);
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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;
            }
        }
    }

    // scala

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    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

    我的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
     * 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;
    }

    该代码返回第n个出现位置子字符串(也称为字段宽度)。例。如果字符串" Stacklowing in low melow"是用于搜索令牌" low"的第二次出现的字符串,则您将与我同意,第二次出现在子代" 18和21"处。 indexOfOccurance("低溢出堆栈中的堆栈",低,2)在字符串中返回18和21。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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));
        }
        }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /* 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;
            }
        }
    }