Java 如何在字符串中找到第n次出现的字符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3976616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 07:49:58  来源:igfitidea点击:

How to find nth occurrence of character in a string?

javastringsubstring

提问by Gnanam

Similar to a question posted here, am looking for a solution in Java.

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

That is, how to find the index of nth occurrence of a character/string from a string?

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

Example:"/folder1/folder2/folder3/". In this case, if I ask for 3rd occurrence of slash (/), it appears before folder3, and I expect to return this index position. My actual intention is to substring it from nth occurrence of a character.

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

Is there any convenient/ready-to-use method available in Java API or do we need to write a small logic on our own to solve this?

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

Also,

还,

  1. I quickly searched whether any method is supported for this purpose at Apache Commons Lang's StringUtils, but I don't find any.
  2. Can regular expressions help in this regard?
  1. 我在 Apache Commons Lang 的StringUtils 上快速搜索了是否支持任何方法用于此目的,但我没有找到任何方法。
  2. 正则表达式在这方面有帮助吗?

回答by Jon Skeet

Two simple options occur:

出现两个简单的选项:

  • Use charAt()repeatedly
  • Use indexOf()repeatedly
  • charAt()反复使用
  • indexOf()反复使用

For example:

例如:

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

That may well not perform as well as using indexOfrepeatedly, but it's possibly simpler to get right.

这可能不如indexOf重复使用效果好,但正确使用可能更简单。

回答by The Archetypal Paul

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

Match anything followed by / two times, then again. The third one is the one you want

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

The Matcherstate can be used to tell where the last / is

匹配器的状态可以被用来告诉其中最后一个/是

回答by aioobe

If your project already depends on Apache Commons you can use StringUtils.ordinalIndexOf, otherwise, here's an implementation:

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


This post has been rewritten as an article here.

这篇文章在这里被改写为一篇文章。

回答by Saul

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

回答by andcoz

You can try something like this:

你可以尝试这样的事情:

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

Note that I did some assumptions in the regex:

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

  • the input path is absolute (i.e. starts with "/");
  • you do not need the 3rd "/" in the result.
  • 输入路径是绝对的(即以“/”开头);
  • 结果中不需要第三个“/”。


As requested in a comment, I'll try to explain the regex: (/[^/]*){2}/([^/]*)

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

Regular expression visualization

正则表达式可视化

  • /[^/]*is a /followed by [^/]*(any number of characters that are not a /),
  • (/[^/]*)groups the previous expression in a single entity. This is the 1st group of the expression,
  • (/[^/]*){2}means that the group must match extactly {2}times,
  • [^/]*is again any number of characters that are not a /,
  • ([^/]*)groups the previos expression in a single entity. This is the 2nd group of the expression.
  • /[^/]*是 a/后跟[^/]*(任意数量的不是 a 的字符/),
  • (/[^/]*)将前一个表达式组合在一个实体中。这是1表达式的st 组,
  • (/[^/]*){2}意味着该组必须精确匹配{2}时间,
  • [^/]*又是任意数量的不是 a 的字符/
  • ([^/]*)将先前的表达式组合在一个实体中。这是2表达式的nd 组。

This way you have only to get the substring that matches the 2nd group: return m.group(2);

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

Image courtesy by Debuggex

图片由Debuggex 提供

回答by Marimuthu Madasamy

Another approach:

另一种方法:

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

回答by Al Belsky

I believe the easiest solution for finding the Nth occurrence of a String is to use StringUtils.ordinalIndexOf()from Apache Commons.

我相信查找第 N 个字符串的最简单解决方案是使用Apache Commons 中的StringUtils.ordinalIndexOf()

Example:

例子:

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

回答by Goofy

I made a few changes to aioobe's answer and got a nth lastIndexOf version, and fix some NPE problems. See code below:

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

回答by Rose

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

回答by Chexpir

Nowadays there IS support of Apache Commons Lang's StringUtils,

现在有 Apache Commons Lang 的StringUtils 支持

This is the primitive:

这是原语:

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

for your problem you can code the following: StringUtils.ordinalIndexOf(uri, "/", 3)

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

You can also find the last nth occurrence of a character in a string with the lastOrdinalIndexOfmethod.

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