Index de toutes les occurrences de caractère dans une chaîne


101

Le code suivant imprimera 2

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

Je voudrais savoir comment obtenir tous les index de "n" ("guess") dans la chaîne "bannanas"

Le résultat attendu serait: [2,3,5]

Réponses:


162

Cela devrait imprimer la liste des postes sans -1la fin que la solution de Peter Lawrey a eue.

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

Cela peut également être fait en forboucle:

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

[Note: si guesspeut être plus long qu'un seul caractère, alors il est possible, en analysant la guesschaîne, de boucler wordplus vite que les boucles ci-dessus. La référence pour une telle approche est l' algorithme de Boyer-Moore . Cependant, les conditions qui favoriseraient l’utilisation d’une telle approche ne semblent pas réunies.]


28

Essayez ce qui suit (qui n'imprime pas -1 à la fin maintenant!)

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

1
vous imprimez toujours -1 à la fin
lukastymo

@Peter Merci beaucoup pour votre réponse, cela semble être juste, mais c'est en fait mon premier jour avec Java donc je suis un peu confus par le résultat final, cela semble générer -1 à la fin et je ne le fais pas ' Je comprends très bien pourquoi! Merci!!
Trufa

@Trufa: Il imprime toujours -1 à la fin car indexOfrenvoie -1 lorsque le caractère n'est pas trouvé.
ColinD le

@Trufa - la raison pour laquelle il imprime -1à la fin est que la doboucle exécute le corps et le découvre ensuiteindex == -1 à la fin while.
Ted Hopp

@ColinD cette partie que j'obtiens, ce que je ne comprends pas, c'est ce qui se passe avec la fonction pour que cela se produise, il "boucle" le mot à la recherche de l'occurrence du caractère et jusqu'à ce que ce soit le cas, il ne peut plus trouver de correct ? et imprime ce dernier index de qui est le non trouvé (-1), est-ce ce qui se passe? (Je ne sais pas si cela s'est bien passé)
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);
    }
}

Le résultat serait utilisé comme ceci:

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

Ou sous forme de tableau:

list.toArray();


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

2

Cela peut être fait de manière fonctionnelle avec Java 9 en utilisant une expression régulière:

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

Voici la solution Kotlin pour ajouter cette logique en tant que nouvelle méthode dans l' CharSequenceAPI à l'aide de la méthode d'extension:

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

L'idée générale est juste, mais word.substring(word)ne compile pas. : P
Peter Lawrey

1
A toujours un problème: il imprime en continu 2.
POSIX_ME_HARDER

Gosh, j'ai besoin de javac tout ce que je poste ici.
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

Aussi, si vous voulez trouver tous les index d'une chaîne dans une chaîne.

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

Ceci est intéressant en ce qu'il soulève une ambiguïté dans la signification de «toutes les occurrences». Si guess c'était "aba"et wordétait "ababa", il n'est pas clair si le guessse produit une ou deux fois dans word. (Je veux dire, il est clair que l'on peut trouver à guesspartir de deux positions distinctes, mais comme les occurrences se chevauchent, il n'est pas clair si elles doivent toutes deux être comptées.) Cette réponse considère que les occurrences qui se chevauchent ne sont pas comptées comme distinctes. Bien sûr, puisque le libellé de OP suggère fortement qu'il guessaura toujours la longueur 1, l'ambiguïté ne se pose pas.
Ted Hopp

0

J'ai eu ce problème aussi, jusqu'à ce que je trouve cette méthode.

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

Cette méthode peut être utilisée pour rechercher des index de n'importe quel indicateur de n'importe quelle longueur dans une chaîne, par exemple:

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

Une classe pour fendre les cordes que j'ai inventée. Un court test est fourni à la fin.

SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts) sera divisé par des espaces sans casser les mots, si possible, et sinon, sera divisé par des index selon maxLen.

Autres méthodes fournies pour contrôler la façon dont il est divisé: 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;
  }
}

Code de test simple:

  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

Ceci est une solution 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

Cela peut être fait en itérant myStringet en déplaçant le fromIndexparamètre dans indexOf():

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }

Avez-vous même essayé d'exécuter ce code? Il imprimera chaque position (0, 1, 2, ...) jusqu'à l'index de la dernière occurrence de mySubstring, indépendamment du fait que l' mySubstringon puisse trouver à chaque position. Pas du tout ce que voulait OP ..
Ted Hopp

-4

Essaye ça

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

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

Ceci est utile pour compter les instances d'une sous-chaîne dans une chaîne plus grande, mais ne renvoie pas les indices des correspondances.
fiveclubs

Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la façon et / ou pourquoi il résout le problème améliorerait la valeur à long terme de la réponse.
Nic3500

Cela ne répond pas à la question. La question nécessite une liste de tous les indices
sheu
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.