Indeks dari semua kemunculan karakter dalam sebuah string

101

Kode berikut akan mencetak 2

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

Saya ingin tahu bagaimana mendapatkan semua indeks "n" ("tebak") dalam string "bannanas"

Hasil yang diharapkan adalah: [2,3,5]

Trufa
sumber

Jawaban:

162

Ini harus mencetak daftar posisi tanpa -1di akhir yang solusi Peter Lawrey ini telah memiliki.

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

Ini juga bisa dilakukan sebagai forloop:

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

[Catatan: jika guessbisa lebih dari satu karakter, maka dimungkinkan, dengan menganalisis guessstring, untuk mengulang wordlebih cepat daripada loop di atas. Tolok ukur untuk pendekatan semacam itu adalah algoritma Boyer-Moore . Namun, kondisi yang mendukung penggunaan pendekatan seperti itu tampaknya tidak ada.]

Ted Hopp
sumber
28

Coba yang berikut ini (Yang tidak mencetak -1 di akhir sekarang!)

int index = word.indexOf(guess);
while(index >= 0) {
   System.out.println(index);
   index = word.indexOf(guess, index+1);
}
Peter Lawrey
sumber
1
Anda selalu mencetak -1 di akhir
lukastymo
@Peter Terima kasih banyak atas jawaban Anda, sepertinya benar, tetapi ini sebenarnya adalah hari pertama saya dengan Java jadi saya sedikit bingung dengan hasil akhirnya, ini sepertinya output -1 di akhir dan saya tidak ' Saya tidak begitu mengerti mengapa! Terima kasih!!
Trufa
@ Trufa: Ini selalu mencetak -1 di akhir karena indexOfmengembalikan -1 ketika karakter tidak ditemukan.
ColinD
@ Trufa - alasan mencetak -1di akhir adalah bahwa doloop mengeksekusi tubuh dan kemudian menemukan itu index == -1di terminating while.
Ted Hopp
@ColinD bagian yang saya dapatkan, apa yang saya tidak mengerti adalah apa yang terjadi dengan fungsi untuk itu terjadi, itu "loop" melalui kata mencari kemunculan karakter dan sampai itu tidak dapat menemukan lagi yang benar ? dan mencetak indeks terakhir ini yang tidak ditemukan (-1), apakah itu yang terjadi? (Saya tidak tahu apakah itu keluar dengan benar)
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);
    }
}

Hasil akan digunakan seperti ini:

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

Atau sebagai array:

list.toArray();
POSIX_ME_HARDER
sumber
4

Dengan Java9, seseorang dapat menggunakan hal-hal iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)berikut: -

List<Integer> indexes = IntStream
          .iterate(word.indexOf(c), index -> index >= 0, index -> word.indexOf(c, index + 1))
          .boxed()
          .collect(Collectors.toList());
System.out.printlnt(indexes);
Naman
sumber
3
int index = -1;
while((index = text.indexOf("on", index + 1)) >= 0) {
   LOG.d("index=" + index);
}
urSus
sumber
2

Ini dapat dilakukan secara fungsional dengan Java 9 menggunakan ekspresi reguler:

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

Berikut Solusi Kotlin untuk menambahkan logika ini sebagai metode baru ke dalam CharSequenceAPI menggunakan metode ekstensi:

 // 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]
Pavneet_Singh
sumber
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);
}
asgs
sumber
Ide umumnya benar, tetapi word.substring(word)tidak dapat dikompilasi. : P
Peter Lawrey
1
Masih ada masalah: mencetak terus menerus 2.
POSIX_ME_HARDER
Astaga, saya perlu javac semua yang saya posting di sini.
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);
idris yıldız
sumber
0

Juga, jika u ingin menemukan semua indeks dari sebuah String dalam sebuah String.

int index = word.indexOf(guess);
while (index >= 0) {
    System.out.println(index);
    index = word.indexOf(guess, index + guess.length());
}
Elite Vip
sumber
Ini menarik karena memunculkan ambiguitas dalam arti "semua kejadian". Jika guess dulu "aba"dan worddulu "ababa", tidak jelas apakah guessterjadi sekali atau dua kali dalam word. (Maksud saya, jelas bahwa seseorang dapat menemukan guessmulai dari dua posisi berbeda, tetapi karena kemunculannya tumpang tindih, tidak jelas apakah keduanya harus dihitung.) Jawaban ini berpandangan bahwa kejadian yang tumpang tindih tidak dihitung sebagai berbeda. Tentu saja, karena kata-kata OP sangat menyarankan bahwa guessakan selalu memiliki panjang 1, ambiguitas tidak muncul.
Ted Hopp
0

Saya memiliki masalah ini juga, sampai saya menemukan metode ini.

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

Metode ini dapat digunakan untuk menemukan indeks bendera apa pun dengan panjang berapa pun dalam string, misalnya:

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);
    }
}
Ian S.
sumber
0

Kelas untuk memisahkan string yang saya buat. Tes singkat disediakan di akhir.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) akan dipisahkan dengan spasi tanpa memutuskan kata, jika memungkinkan, dan jika tidak, akan dipisahkan dengan indeks sesuai maxLen.

Metode lain yang disediakan untuk mengontrol bagaimana itu dibagi: 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;
  }
}

Kode tes sederhana:

  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();
  }
Dariusz
sumber
0

Ini adalah solusi 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;
    }
Bamidele Alegbe
sumber
-1

Ini dapat dilakukan dengan mengiterasi myStringdan menggeser fromIndexparameter di indexOf():

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }
Zon
sumber
Apakah Anda bahkan mencoba menjalankan kode ini? Ini akan mencetak setiap posisi (0, 1, 2, ...) hingga indeks kemunculan terakhir mySubstring, terlepas dari apakah mySubstringdapat ditemukan di setiap posisi. Tidak sama sekali yang diinginkan OP ..
Ted Hopp
-4

Coba ini

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

System.out.println(StringUtils.countMatches(str, findStr));
Vikas Kumbhar
sumber
Ini bagus untuk menghitung instance substring dalam string yang lebih besar, tetapi tidak mengembalikan indeks kecocokan.
fiveclubs
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa kode ini memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
Nic3500
Ini tidak menjawab pertanyaan itu. Pertanyaannya membutuhkan daftar semua indeks
sheu