Bir dizedeki tüm karakter oluşumlarının dizini


101

Aşağıdaki kod 2 yazdıracaktır

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

"Bannanas" dizesindeki "n" ("tahmin") indekslerinin nasıl elde edileceğini öğrenmek istiyorum.

Beklenen sonuç şöyle olacaktır: [2,3,5]

Yanıtlar:


162

Bu -1, Peter Lawrey'nin çözümünün sahip olduğu en sonunda pozisyonların listesini yazdırmalıdır .

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

Bir fordöngü olarak da yapılabilir :

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

[Not: Eğer guesstek bir karakterden daha uzun olabiliyorsa, guessdizeyi analiz ederek word, yukarıdaki döngülerin yaptığından daha hızlı döngü yapmak mümkündür. Böyle bir yaklaşımın ölçütü Boyer-Moore algoritmasıdır . Ancak, böyle bir yaklaşımı kullanmayı tercih edecek koşullar mevcut görünmüyor.]


28

Aşağıdakini deneyin (Şimdi sonunda -1 yazmaz!)

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

1
her zaman sonunda -1 yazdırırsınız
lukastymo

@Peter Cevabınız için çok teşekkür ederim, doğru görünüyor, ama bu aslında Java ile ilk günüm bu yüzden son sonuçtan biraz kafam karıştı, bu sonuçta -1 çıktı gibi görünüyor ve yapmıyorum ' Nedenini tam olarak anlıyorum! Teşekkürler!!
Trufa

@Trufa: Her zaman sonunda -1 yazdırır çünkü indexOfkarakter bulunamadığında -1 döndürür.
ColinD

@Trufa - -1Sonunda yazdırmasının nedeni , dodöngünün gövdeyi yürütmesi ve ardından bunu index == -1sonlandırmada keşfetmesidir while.
Ted Hopp

@ColinD aldığım kısım, anlamadığım şey bunun gerçekleşmesi için fonksiyonda ne olduğu, karakterin oluşumunu arayan kelimede "döngü yapıyor" ve o olana kadar artık doğru bulamıyor ? ve bu son indeks bulunamayanın (-1) basar, bu ne oluyor? (Bunun doğru çıkıp çıkmadığını bilmiyorum)
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);
    }
}

Sonuç şu şekilde kullanılacaktır:

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

Veya bir dizi olarak:

list.toArray();


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

3

Bu, Java 9 ile düzenli ifade kullanılarak işlevsel bir şekilde yapılabilir:

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

CharSequenceUzantı yöntemini kullanarak bu mantığı API'ye yeni bir yöntem olarak eklemek için Kotlin Çözümü :

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

Genel fikir doğru, ancak word.substring(word)derlenmeyecek. : P
Peter Lawrey

1
Hala bir sorun var: sürekli yazdırıyor 2.
POSIX_ME_HARDER

Tanrım, buraya yazdığım her şeyi javac etmem gerekiyor.
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

Ayrıca, bir String'in tüm dizinlerini bulmak istiyorsanız.

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

Bu ilginçtir, çünkü "tüm olaylar" anlamında bir belirsizlik yaratır. Eğer guess oldu "aba"ve wordoldu "ababa", eğer net değil guessbir veya iki kez meydana gelir word. (Demek istediğim, birinin guessiki farklı konumdan başlayarak bulabileceği açıktır , ancak olaylar örtüştüğü için ikisinin de sayılması gerekip gerekmediği açık değildir.) Bu yanıt, örtüşen olayların ayrı olarak sayılmadığı görüşünü alır. Elbette, OP'nin ifadesi guessher zaman 1 uzunluğa sahip olacağını kuvvetle önerdiğinden , belirsizlik ortaya çıkmaz.
Ted Hopp

0

Bu yöntemi bulana kadar ben de bu problemi yaşadım.

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

Bu yöntem, bir dizedeki herhangi bir uzunluktaki herhangi bir bayrağın dizinlerini bulmak için kullanılabilir, örneğin:

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

Bulduğum dizeleri bölmek için bir sınıf. Sonunda kısa bir test sağlanır.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) mümkünse sözcükleri bölmeden boşluklara bölünecek ve yoksa maxLen'e göre dizinlere bölünecektir.

Nasıl bölündüğünü kontrol etmek için sağlanan diğer yöntemler: 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;
  }
}

Basit test kodu:

  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

Bu bir java 8 çözümüdür.

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

Bu, aşağıdaki parametreyi yineleyerek myStringve kaydırarak yapılabilir :fromIndexindexOf()

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }

Bu kodu çalıştırmayı hiç denedin mi? Her pozisyonda mySubstringbulunup mySubstringbulunamayacağına bakılmaksızın , son oluşum indeksine kadar her pozisyonu (0, 1, 2, ...) yazdıracaktır . OP'nin istediği hiç de değil ..
Ted Hopp 24'16

-4

Bunu dene

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

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

Bu, daha büyük bir dizedeki bir alt dizenin örneklerini saymak için iyidir, ancak eşleşmelerin dizinlerini döndürmez.
fiveclubs

Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek içerik sağlamak, yanıtın uzun vadeli değerini artıracaktır.
Nic3500

Bu soruya cevap vermiyor. Soru tüm endekslerin bir listesini gerektiriyor
sheu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.