문자열에있는 모든 문자의 색인


101

다음 코드는 2를 인쇄합니다.

String word = "bannanas";
String guess = "n";
int index;
System.out.println( 
    index = word.indexOf(guess)
);

문자열 "bannanas"에서 "n"( "guess")의 모든 인덱스를 얻는 방법을 알고 싶습니다.

예상되는 결과는 다음과 같습니다. [2,3,5]

답변:


162

이것은 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 알고리즘 입니다. 그러나 그러한 접근 방식을 선호하는 조건은 존재하지 않는 것 같습니다.]


28

다음을 시도하십시오 (지금 끝에 -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 : indexOf문자를 찾을 수없는 경우 -1을 반환 하므로 항상 끝에 -1을 인쇄합니다 .
ColinD

@Trufa-인쇄 이유 -1 마지막에 는 do루프가 본문을 실행 한 다음index == -1 종결에서이를 발견하기 때문 입니다 while.
Ted Hopp

@ColinD 내가 얻는 부분, 내가 이해하지 못하는 것은 그 기능이 일어나는 일입니다. 그것은 문자의 발생을 찾는 단어를 "루프"하고 그것이 더 이상 옳지 않을 때까지 찾을 수 있습니다 ? 찾을 수없는 마지막 색인 (-1)을 인쇄합니다. 무슨 일이 일어나고 있습니까? (정확하게
나왔는지

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


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

2

정규 표현식을 사용하여 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]

1
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

0
    String input = "GATATATGCG";
    String substring = "G";
    String temp = input;
    String indexOF ="";
    int tempIntex=1;

    while(temp.indexOf(substring) != -1)
    {
        int index = temp.indexOf(substring);
        indexOF +=(index+tempIntex)+" ";
        tempIntex+=(index+1);
        temp = temp.substring(index + 1);
    }
    Log.e("indexOf ","" + indexOF);

0

또한, 문자열에서 문자열의 모든 인덱스를 찾으려면.

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

이것은 "모든 발생"의 의미에 모호성을 제기한다는 점에서 흥미 롭습니다. 경우 guess 였다 "aba"word이었다 "ababa"(가) 있다면, 그것은 분명하지 않다 guess번 또는 두 번에 발생합니다 word. (내 말은, guess두 개의 서로 다른 위치에서 시작 하는 것을 찾을 수 있다는 것은 분명 하지만, 발생이 겹치기 때문에 둘 다 계산해야하는지 여부는 명확하지 않습니다.)이 대답은 겹치는 발생이 별개로 계산되지 않는다는 관점을 취합니다. 물론 OP의 문구 guess는 항상 길이가 1 이라는 것을 강력하게 암시하기 때문에 모호성은 발생하지 않습니다.
Ted Hopp

0

이 방법을 찾을 때까지이 문제도있었습니다.

public static int[] indexesOf(String s, String flag) {
    int flagLen = flag.length();
    String current = s;
    int[] res = new int[s.length()];
    int count = 0;
    int base = 0;
    while(current.contains(flag)) {
        int index = current.indexOf(flag);
        res[count] = index + base;
        base += index + flagLen;
        current = current.substring(current.indexOf(flag) + flagLen, current.length());
        ++ count;
    }
    return Arrays.copyOf(res, count);
}

이 메서드는 문자열에서 길이에 관계없이 플래그의 인덱스를 찾는 데 사용할 수 있습니다. 예를 들면 다음과 같습니다.

public class Main {

    public static void main(String[] args) {
        int[] indexes = indexesOf("Hello, yellow jello", "ll");

        // Prints [2, 9, 16]
        System.out.println(Arrays.toString(indexes));
    }

    public static int[] indexesOf(String s, String flag) {
        int flagLen = flag.length();
        String current = s;
        int[] res = new int[s.length()];
        int count = 0;
        int base = 0;
        while(current.contains(flag)) {
            int index = current.indexOf(flag);
            res[count] = index + base;
            base += index + flagLen;
            current = current.substring(current.indexOf(flag) + flagLen, current.length());
            ++ count;
        }
        return Arrays.copyOf(res, count);
    }
}

0

내가 생각해 낸 문자열을 나누는 클래스. 마지막에 짧은 테스트가 제공됩니다.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) 가능한 경우 단어를 분리하지 않고 공백으로 분할하고 그렇지 않은 경우 maxLen에 따라 인덱스로 분할합니다.

분할 방법을 제어하기 위해 제공되는 기타 방법 : bruteSplitLimit(String str, int maxLen, int maxParts), spaceSplit(String str, int maxLen, int maxParts).

public class SplitStringUtils {

  public static String[] smartSplitToShorterStrings(String str, int maxLen, int maxParts) {
    if (str.length() <= maxLen) {
      return new String[] {str};
    }
    if (str.length() > maxLen*maxParts) {
      return bruteSplitLimit(str, maxLen, maxParts);
    }

    String[] res = spaceSplit(str, maxLen, maxParts);
    if (res != null) {
      return res;
    }

    return bruteSplitLimit(str, maxLen, maxParts);
  }

  public static String[] bruteSplitLimit(String str, int maxLen, int maxParts) {
    String[] bruteArr = bruteSplit(str, maxLen);
    String[] ret = Arrays.stream(bruteArr)
          .limit(maxParts)
          .collect(Collectors.toList())
          .toArray(new String[maxParts]);
    return ret;
  }

  public static String[] bruteSplit(String name, int maxLen) {
    List<String> res = new ArrayList<>();
    int start =0;
    int end = maxLen;
    while (end <= name.length()) {
      String substr = name.substring(start, end);
      res.add(substr);
      start = end;
      end +=maxLen;
    }
    String substr = name.substring(start, name.length());
    res.add(substr);
    return res.toArray(new String[res.size()]);
  }

  public static String[] spaceSplit(String str, int maxLen, int maxParts) {
    List<Integer> spaceIndexes = findSplitPoints(str, ' ');
    List<Integer> goodSplitIndexes = new ArrayList<>();
    int goodIndex = -1; 
    int curPartMax = maxLen;
    for (int i=0; i< spaceIndexes.size(); i++) {
      int idx = spaceIndexes.get(i);
      if (idx < curPartMax) {
        goodIndex = idx;
      } else {
        goodSplitIndexes.add(goodIndex+1);
        curPartMax = goodIndex+1+maxLen;
      }
    }
    if (goodSplitIndexes.get(goodSplitIndexes.size()-1) != str.length()) {
      goodSplitIndexes.add(str.length());
    }
    if (goodSplitIndexes.size()<=maxParts) {
      List<String> res = new ArrayList<>();
      int start = 0;
      for (int i=0; i<goodSplitIndexes.size(); i++) {
        int end = goodSplitIndexes.get(i);
        if (end-start > maxLen) {
          return null;
        }
        res.add(str.substring(start, end));
        start = end;
      }
      return res.toArray(new String[res.size()]);
    }
    return null;
  }


  private static List<Integer> findSplitPoints(String str, char c) {
    List<Integer> list = new ArrayList<Integer>();
    for (int i = 0; i < str.length(); i++) {
      if (str.charAt(i) == c) {
        list.add(i);
      }
    }
    list.add(str.length());
    return list;
  }
}

간단한 테스트 코드 :

  public static void main(String[] args) {
    String [] testStrings = {
        "123",
        "123 123 123 1123 123 123 123 123 123 123",
        "123 54123 5123 513 54w567 3567 e56 73w45 63 567356 735687 4678 4678 u4678 u4678 56rt64w5 6546345",
        "1345678934576235784620957029356723578946",
        "12764444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444",
        "3463356 35673567567 3567 35 3567 35 675 653 673567 777777777777777777777777777777777777777777777777777777777777777777"
    };

    int max = 35;
    int maxparts = 2;


    for (String str : testStrings) {
      System.out.println("TEST\n    |"+str+"|");
      printSplitDetails(max, maxparts);
      String[] res = smartSplitToShorterStrings(str, max, maxparts);
      for (int i=0; i< res.length;i++) {
        System.out.println("  "+i+": "+res[i]);
      }
      System.out.println("===========================================================================================================================================================");
    }

  }

  static void printSplitDetails(int max, int maxparts) {
    System.out.print("  X: ");
    for (int i=0; i<max*maxparts; i++) {
      if (i%max == 0) {
        System.out.print("|");
      } else {
        System.out.print("-");
      }
    }
    System.out.println();
  }

0

이것은 자바 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하고 이동 하여 수행 할 수 있습니다 .fromIndexindexOf()

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }

이 코드를 실행 해 보셨나요? 각 위치에서 찾을 수 mySubstring있는지 여부에 관계없이의 마지막 발생 인덱스까지 모든 위치 (0, 1, 2, ...)를 인쇄합니다 mySubstring. 아니 영업 이익은 원하는 것을 모두에서 ..
테드 Hopp

-4

이 시도

String str = "helloslkhellodjladfjhello";
String findStr = "hello";

System.out.println(StringUtils.countMatches(str, findStr));

이것은 더 큰 문자열에서 하위 문자열의 인스턴스를 계산하는 데 유용하지만 일치 항목의 인덱스를 반환하지 않습니다.
fiveclubs

이 코드는 질문에 답할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다.
Nic3500

이것은 질문에 대한 답이 아닙니다. 질문에는 모든 지수 목록이 필요합니다
sheu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.