Індекси всіх подій символів у рядку


101

Наступний код надрукує 2

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

Я хотів би знати, як отримати всі індекси "n" ("здогад") у рядку "bannanas"

Очікуваним результатом буде: [2,3,5]

Відповіді:


162

Це повинно вивести список позицій без -1наприкінці , що рішення Пітера Lawrey в уже мав.

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швидше, ніж це роблять вищевказані петлі. Орієнтиром такого підходу є алгоритм Бойєра-Мура . Однак, схоже, умови, які б сприяли використанню такого підходу, схоже, відсутні.]


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: Він завжди друкує -1 в кінці, тому що indexOfповертає -1, коли символ не знайдено.
ColinD

@Trufa - причина, яку він друкує -1в кінці, полягає в тому, що doцикл виконує тіло, а потім виявляє це index == -1в завершенні while.
Тед Хопп

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

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
Пітер Лорі

1
Проблема все ще є: друкується постійно 2.
POSIX_ME_HARDER

Боже, мені потрібно яваку все, що я публікую тут.
асгс

1

Це можна зробити функціонально з 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
    );

Ось рішення Kotlin для додавання цієї логіки як нових нових методів в CharSequenceAPI, використовуючи метод розширення:

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

Крім того, якщо ви хочете знайти всі індекси рядка в рядку.

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починаючи з двох різних позицій, але, оскільки зустрічаються випадки, не зрозуміло, чи слід їх обидва рахувати.) Ця відповідь вважає, що випадки, що перекриваються, не вважаються різними. Звичайно, оскільки формулювання ОП настійно говорить про те, що guessзавжди буде тривалість 1, двозначності не виникає.
Тед Хопп

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

Це рішення 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

Це можна зробити за допомогою ітерації myStringта зміщення fromIndexпараметра у indexOf():

  int currentIndex = 0;

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

    System.out.println(currentIndex);

    currentIndex++;
  }

Ви навіть намагалися запустити цей код? Він буде друкувати кожну позицію (0, 1, 2, ...) до індексу останнього виникнення mySubstring, незалежно від того, чи mySubstringможна їх знайти в кожній позиції. Зовсім не те, чого хотів ОП ..
Тед Хопп

-4

Спробуйте це

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

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

Це добре для підрахунку примірників підрядків у більшому рядку, але не повертає індекси збігів.
п'ять клубів

Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, як та / або чому він вирішує проблему, покращить довгострокове значення відповіді.
Nic3500

Це не дає відповіді на запитання. Питання вимагає переліку всіх індексів
sheu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.