Chỉ mục của tất cả các lần xuất hiện của ký tự trong một chuỗi


101

Đoạn mã sau sẽ in 2

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

Tôi muốn biết cách lấy tất cả các chỉ mục của "n" ("đoán") trong chuỗi "bannanas"

Kết quả mong đợi sẽ là: [2,3,5]

Câu trả lời:


162

Điều này sẽ in ra danh sách các vị trí không có -1cuối mà giải pháp của Peter Lawrey đã có.

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

Nó cũng có thể được thực hiện như một forvòng lặp:

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

[Lưu ý: nếu guesscó thể dài hơn một ký tự, thì bằng cách phân tích guesschuỗi, có thể lặp lại wordnhanh hơn các vòng ở trên. Tiêu chuẩn cho cách tiếp cận như vậy là thuật toán Boyer-Moore . Tuy nhiên, các điều kiện có lợi cho việc sử dụng cách tiếp cận như vậy dường như không có.]


28

Hãy thử cách sau (Cái nào không in -1 ở cuối bây giờ!)

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

1
bạn luôn in -1 ở cuối
lukastymo

@Peter Cảm ơn bạn rất nhiều vì câu trả lời của bạn, có vẻ đúng, nhưng đây thực sự là ngày đầu tiên của tôi với Java nên tôi hơi bối rối trước kết quả cuối cùng, điều này dường như xuất ra -1 ở cuối an I don ' t khá hiểu tại sao! cảm ơn!!
Trufa

@Trufa: Nó luôn in -1 ở cuối vì indexOftrả về -1 khi không tìm thấy ký tự.
ColinD

@Trufa - lý do nó in -1ở cuối là dovòng lặp thực thi phần thân và sau đó phát hiện ra điều đó index == -1trong phần kết thúc while.
Ted Hopp

@ColinD mà phần tôi nhận được, điều tôi không hiểu là điều gì đang xảy ra với hàm để điều đó xảy ra, nó "lặp" qua từ tìm kiếm sự xuất hiện của ký tự và cho đến khi nó không thể tìm thấy đúng nữa ? và in ra chỉ mục cuối cùng này là không tìm thấy (-1), đó là điều gì đang xảy ra? (Tôi không biết liệu điều đó có đúng không)
Trufa

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

Kết quả sẽ được sử dụng như thế này:

    for(Integer i : list){
        System.out.println(i);
    }

Hoặc dưới dạng một mảng:

list.toArray();


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

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

Ý tưởng chung là đúng, nhưng word.substring(word)sẽ không biên dịch. : P
Peter Lawrey

1
Vẫn có sự cố: nó in liên tục 2.
POSIX_ME_HARDER

Chúa ơi, tôi cần javac mọi thứ tôi đăng ở đây.
asgs

1

Điều này có thể được thực hiện theo cách chức năng với Java 9 bằng cách sử dụng biểu thức chính quy:

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

Đây là Giải pháp Kotlin để thêm logic này dưới dạng một phương thức mới vào CharSequenceAPI bằng cách sử dụng phương thức mở rộng:

 // 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]

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

Ngoài ra, nếu bạn muốn tìm tất cả các chỉ mục của một chuỗi trong một chuỗi.

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

Điều này thú vị ở chỗ nó làm dấy lên sự mơ hồ trong ý nghĩa của "tất cả các lần xuất hiện". Nếu guess đã "aba"wordđang xảy ra "ababa", không rõ nếu điều đó guessxảy ra một lần hay hai lần trong word. (Ý tôi là, rõ ràng là người ta có thể tìm thấy guessbắt đầu ở hai vị trí khác nhau, nhưng vì các lần xuất hiện trùng lặp nên không rõ liệu cả hai có nên được tính hay không.) Câu trả lời này cho thấy rằng các lần xuất hiện trùng lặp không được tính là riêng biệt. Tất nhiên, vì từ ngữ của OP gợi ý rõ ràng rằng guesssẽ luôn có độ dài 1, nên sự mơ hồ không phát sinh.
Ted Hopp

0

Tôi cũng gặp vấn đề này, cho đến khi tôi nghĩ ra phương pháp này.

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

Phương thức này có thể được sử dụng để tìm các chỉ mục của bất kỳ cờ nào có độ dài bất kỳ trong một chuỗi, ví dụ:

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

Một lớp học để tách chuỗi mà tôi đã nghĩ ra. Một bài kiểm tra ngắn được cung cấp ở cuối.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) sẽ chia theo dấu cách mà không ngắt từ, nếu có thể, và nếu không, sẽ chia theo chỉ mục theo maxLen.

Các phương pháp khác được cung cấp để kiểm soát cách nó được phân chia: 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;
  }
}

Mã kiểm tra đơn giản:

  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

Đây là một giải pháp 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

Điều này có thể được thực hiện bằng cách lặp myStringvà chuyển fromIndextham số trong indexOf():

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }

Bạn thậm chí đã thử chạy mã này? Nó sẽ in ra mọi vị trí (0, 1, 2, ...) cho đến chỉ mục của lần xuất hiện cuối cùng mySubstring, bất kể mySubstringcó thể tìm thấy ở mỗi vị trí hay không. Không phải ở tất cả những gì OP muốn ..
Ted Hopp

-4

Thử cái này

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

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

Điều này tốt để đếm các trường hợp của một chuỗi con trong một chuỗi lớn hơn, nhưng không trả về các chỉ số của các kết quả phù hợp.
fiveclubs

Mặc dù mã này có thể trả lời câu hỏi, nhưng việc cung cấp thêm ngữ cảnh về cách và / hoặc lý do tại sao nó giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Nic3500,

Điều này không trả lời câu hỏi. Câu hỏi yêu cầu danh sách tất cả các chỉ số
sheu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.