如何在字符串中查找第 n 个出现的字符?
Posted
技术标签:
【中文标题】如何在字符串中查找第 n 个出现的字符?【英文标题】:How to find nth occurrence of character in a string? 【发布时间】:2011-04-27 22:59:09 【问题描述】:类似于here 发布的问题,我正在寻找 在 Java 中的解决方案。
即如何从一个字符串中找到一个字符/字符串第n次出现的索引?
示例:“/folder1/folder2/folder3/”。 在这种情况下,如果我要求第三次出现斜杠 (/),它会出现在 folder3 之前,并且我希望返回这个索引位置。我的实际意图是从第 n 次出现的字符中对其进行子串化。
Java API 中是否有任何方便/即用的方法,或者我们需要自己编写一个小逻辑来解决这个问题?
还有,
-
我在 Apache Commons Lang 的StringUtils 上快速搜索是否支持任何方法用于此目的,但没有找到。
正则表达式可以在这方面提供帮助吗?
【问题讨论】:
对于您的特定示例,根据您想要对结果执行的操作,在 / 上拆分字符串可能更容易,这可能会直接为您提供所需的内容? @Paul:这也是个好主意。 【参考方案1】:如果您的项目已经依赖于 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。
【讨论】:
除了“off-by-one”错误之外,@Jon Skeet 的解决方案还有另一个很大的好处 - 通过小调整(反转循环),您可以从最后一个”。 @KaranChadha,同样适用于这个解决方案。只需更改为lastIndexOf
。【参考方案2】:
我相信查找第 N 次出现的字符串的最简单解决方案是使用来自 Apache Commons 的 StringUtils.ordinalIndexOf()。
例子:
StringUtils.ordinalIndexOf("aabaabaa", "b", 2) == 5
【讨论】:
【参考方案3】:有两个简单的选择:
反复使用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
好,但它可能更容易正确处理。
【讨论】:
【参考方案4】:你可以试试这样的:
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/([^/]*)
/[^/]*
是 /
后跟 [^/]*
(任意数量的非 /
字符),
(/[^/]*)
将前一个表达式组合在一个实体中。这是表达式的1
st 组,
(/[^/]*)2
表示该组必须完全匹配 2
次,
[^/]*
又是任意数量的不是/
的字符,
([^/]*)
将 previos 表达式组合在一个实体中。这是表达式的 2
nd 组。
这样你只需要得到匹配第二组的子字符串:return m.group(2);
图片由Debuggex提供
【讨论】:
你能用简单的英语解释一下正则表达式吗?喜欢:反斜杠后面跟着任何不是反斜杠的无限时间......然后我不确定。 @Ced,我为正则表达式添加了解释和小修复。我希望现在更清楚了。 感谢您解释正则表达式。【参考方案5】:我对 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;
【讨论】:
我认为如果给定null
作为参数,该方法抛出 NPE 是合理的。这是标准库中最常见的行为。【参考方案6】:
([.^/]*/)2[^/]*(/)
匹配任何后跟 / 两次,然后再匹配一次。第三个就是你要的那个
Matcher 状态可以用来判断最后一个 / 在哪里
【讨论】:
我确信这是一个非常酷的答案,但是我如何在我的代码中使用它呢? 看@andcoz的回答(正则表达式不同,但思路一样)【参考方案7】:也许你也可以通过 String.split(..) 方法来实现。
String str = "";
String[] tokens = str.split("/")
return tokens[nthIndex] == null
【讨论】:
【参考方案8】: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;
【讨论】:
【参考方案9】:另一种方法:
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);
【讨论】:
【参考方案10】:现在支持 Apache Commons Lang 的 StringUtils,
这是原语:
int org.apache.commons.lang.StringUtils.ordinalIndexOf(CharSequence str, CharSequence searchStr, int ordinal)
对于您的问题,您可以编写以下代码:StringUtils.ordinalIndexOf(uri, "/", 3)
您还可以使用 lastOrdinalIndexOf 方法查找字符串中字符的最后第 n 次出现。
【讨论】:
【参考方案11】:这个答案改进了@aioobe 的答案。该答案中的两个错误已修复。 1. n=0 应该返回 -1。 2. 第 n 次出现返回 -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;
【讨论】:
【参考方案12】:我的解决方案:
/**
* 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】: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;
【讨论】:
【参考方案14】:/* 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】:代码返回第 n 个出现位置的子字符串,即字段宽度。例子。如果字符串 "Stack overflow in low melow" 是搜索 2nd 标记“low”出现的字符串,你会同意我的说法,它第二次出现在 subtring “18 和 21”。 indexOfOccurance("low melow 堆栈溢出", low, 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));
【讨论】:
【参考方案16】: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;
【讨论】:
虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请编辑您的答案以添加解释并说明适用的限制和假设。【参考方案17】://斯卡拉
// 如果该值第 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
【讨论】:
【参考方案18】:APACHE 实现(复制粘贴:不要为一个函数导入整个库!)
这里是与他们的 StringUtils 库分离的确切 Apache Commons 实现(这样您就可以复制粘贴这个并且不必为一个函数添加库的依赖项):
/**
* <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;
【讨论】:
【参考方案19】:看起来你想要子串的字符串是一个文件路径。您不能只按/
拆分,然后从感兴趣的点开始使用数组条目吗?例如,
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());
【讨论】:
【参考方案20】:static int nthOccurrenceOfChar(String str, int n, char ch)
int count = 0;
for (int i = 0; i < str.length(); i++)
if (str.charAt(i) == ch && ++count == n)
return i;
return -1;
【讨论】:
以上是关于如何在字符串中查找第 n 个出现的字符?的主要内容,如果未能解决你的问题,请参考以下文章