字符串中某个字符的所有出现位置索引

128
以下代码将打印2。
String word = "bannanas";
String guess = "n";
int index;
System.out.println( 
    index = word.indexOf(guess)
);
我想知道如何获取字符串"bannanas"中所有字母"n"("guess")的索引。
预期结果应为:[2,3,5]
16个回答

196

这应该打印出位置列表,但末尾不包含Peter Lawrey的解决方案中的-1

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + 1);
}

这也可以使用 for 循环实现:

for (int index = word.indexOf(guess);
     index >= 0;
     index = word.indexOf(guess, index + 1))
{
    System.out.println(index);
}
[注意:如果guess可以超过一个字符,那么通过分析guess字符串,可以比上面的循环更快地循环word。这种方法的基准是Boyer-Moore算法。然而,似乎不存在有利于使用这种方法的条件。]

31

尝试以下方法(现在不会在结尾处打印-1!)

int index = word.indexOf(guess);
while(index >= 0) {
   System.out.println(index);
   index = word.indexOf(guess, index+1);
}

1
你总是在最后打印-1 - lukastymo
@Peter非常感谢您的回答,看起来似乎是正确的,但这实际上是我第一天接触Java,所以最终结果让我有点困惑,它似乎在最后输出-1,我不太明白为什么!谢谢!! - Trufa
@Trufa:它总是在结尾打印-1,因为当字符未被找到时,indexOf返回-1。 - ColinD
@Trufa - 打印最后的“-1”的原因是do循环执行主体,然后在终止的while中发现index == -1 - Ted Hopp
@ColinD,我理解了那部分内容,但我不明白的是函数发生了什么事情,它会“循环”查找单词中的字符出现次数,直到找不到为止,对吗?然后打印出最后一个未找到的索引(-1),是这样吗?(我不知道我是否表达清楚) - Trufa
@Trufa:是的,它总是在检查是否为-1之前打印索引。 - ColinD

14

使用Java 9和正则表达式可以以函数式方式完成此操作:

Pattern.compile(Pattern.quote(guess)) // sanitize input and create pattern
            .matcher(word) // create matcher
            .results()     // get the MatchResults, Java 9 method
            .map(MatchResult::start) // get the first index
            .collect(Collectors.toList()) // collect found indices into a list
    );

这是将此逻辑作为新方法添加到 CharSequence API 中的 Kotlin 解决方案,使用扩展方法:

 // Extension method
fun CharSequence.indicesOf(input: String): List<Int> =
    Regex(Pattern.quote(input)) // build regex
        .findAll(this)          // get the matches
        .map { it.range.first } // get the index
        .toCollection(mutableListOf()) // collect the result as list

// call the methods as
"Banana".indicesOf("a") // [1, 3, 5]

9
String string = "bannanas";
ArrayList<Integer> list = new ArrayList<Integer>();
char character = 'n';
for(int i = 0; i < string.length(); i++){
    if(string.charAt(i) == character){
       list.add(i);
    }
}

结果将会被这样使用:
    for(Integer i : list){
        System.out.println(i);
    }

或者作为一个数组:
list.toArray();

op的guess变量是一个字符串。您的解决方案只适用于字符。 - theprogrammer

7

4
int index = -1;
while((index = text.indexOf("on", index + 1)) >= 0) {
   LOG.d("index=" + index);
}

4

Java 8+

要查找字符串中特定字符的所有索引,可以创建一个包含所有索引的IntStream并在其上进行filter操作。

import java.util.stream.Collectors;
import java.util.stream.IntStream;
//...
String word = "bannanas";
char search = 'n';
//To get List of indexes:
List<Integer> indexes = IntStream.range(0, word.length())
        .filter(i -> word.charAt(i) == search).boxed()
        .collect(Collectors.toList());
//To get array of indexes:
int[] indexes = IntStream.range(0, word.length())
        .filter(i -> word.charAt(i) == search).toArray();

3
String word = "bannanas";

String guess = "n";

String temp = word;

while(temp.indexOf(guess) != -1) {
     int index = temp.indexOf(guess);
     System.out.println(index);
     temp = temp.substring(index + 1);
}

整体思路没错,但是 word.substring(word) 无法编译。 :P - Peter Lawrey
1
仍然存在一个问题:它不断地打印出2。 - POSIX_ME_HARDER
天啊,我需要在这里发布的所有内容都进行javac编译。 - asgs

2
这是一个Java 8的解决方案。
public int[] solution (String s, String subString){
        int initialIndex = s.indexOf(subString);
        List<Integer> indexList = new ArrayList<>();
        while (initialIndex >=0){
            indexList.add(initialIndex);
            initialIndex = s.indexOf(subString, initialIndex+1);
        }
        int [] intA = indexList.stream().mapToInt(i->i).toArray();
        return intA;
    }

1

这可以通过迭代myString并在indexOf()中移动fromIndex参数来完成:

  int currentIndex = 0;

  while (
    myString.indexOf(
      mySubstring,
      currentIndex) >= 0) {

    System.out.println(currentIndex);

    currentIndex++;
  }

你有试过运行这段代码吗?它会打印出每个位置(0、1、2...)直到最后一个mySubstring出现的索引位置,而不管mySubstring是否在每个位置都能找到。这完全不是OP想要的。 - Ted Hopp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接