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

Gna*_*nam 87 java string substring

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

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

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

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

也,

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

aio*_*obe 123

如果您的项目已经依赖于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;
}
Run Code Online (Sandbox Code Playgroud)

该帖子已被改写为一篇文章在这里.


Al *_*sky 57

我相信找到第N个String的最简单的解决方案是使用Apache Commons的StringUtils.ordinalIndexOf().

例:

StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  == 5
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 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;
}
Run Code Online (Sandbox Code Playgroud)

这可能不如indexOf重复使用那么好,但是可能更容易做对.


and*_*coz 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

正则表达式可视化

  • /[^/]*是一个/后跟[^/]*(任何数量的不属于字符的/),
  • (/[^/]*)将前一个表达式分组到一个实体中.这是1表达式的st组,
  • (/[^/]*){2}表示该组必须匹配的{2}时间,
  • [^/]*又是任何数量的不是a的字符/,
  • ([^/]*)将previos表达式分组到单个实体中.这是2表达式的第n组.

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

图片由Debuggex提供


Goo*_*ofy 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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为如果给出`null`作为参数,该方法抛出NPE是合理的.这是标准库中最常见的行为. (3认同)

The*_*aul 5

 ([.^/]*/){2}[^/]*(/)
Run Code Online (Sandbox Code Playgroud)

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

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


小智 5

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

String str = "";
String[] tokens = str.split("/")
return tokens[nthIndex] == null 
Run Code Online (Sandbox Code Playgroud)