Indeksy wszystkich wystąpień znaku w ciągu


Poniższy kod wyświetli 2
String word = "bannanas";
String guess = "n";
int index;
System.out.println(
index = word.indexOf(guess));

Chciałbym wiedzieć, jak uzyskać wszystkie indeksy „n” („zgadnij”) w wierszu „banany”
Oczekiwany wynik to:
[2, 3, 5]
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Powinno to wypisać listę pozycji bez
-1
na końcu, co
<strike>
był
</strike>
w

Rozwiązania Petera Lowry'ego
https://stackoverflow.com/a/5034468/535871
.
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index + 1);
}

Można to również zrobić jako pętlę
for
:
for (int index = word.indexOf(guess);
index >= 0;
index = word.indexOf(guess, index + 1))
{
System.out.println(index);
}

[Uwaga: jeśli
guess
może być dłuższe niż jeden znak, możesz, analizując ciąg
guess
, przechodzić przez
word
szybciej niż powyższe pętle ... Punktem odniesienia dla tego podejścia jest

Algorytm Boyera-Moore'a
https://en.wikipedia.org/wiki/ ... hm... Jednak wydaje się, że nie istnieje środowisko sprzyjające temu podejściu.]
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Spróbuj wykonać następujące czynności (co teraz nie wyświetla na końcu -1!)
int index = word.indexOf(guess);
while(index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index+1);
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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

Wynik zostanie użyty w następujący sposób:
for(Integer i : list){
System.out.println(i);
}

Lub jako tablica:
list.toArray();
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Z Java9 można korzystać
iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)
https://docs.oracle.com/javase ... ator-
w następujący sposób:-
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);
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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

Anonimowy użytkownik

Potwierdzenie od:

Można to zrobić w funkcjonalny sposób w Javie 9 przy użyciu wyrażenia regularnego:
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
);

Oto rozwiązanie Kotlin umożliwiające dodanie tej logiki jako nowych metod do interfejsu API
CharSequence
przy użyciu metody rozszerzenia:
// 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]
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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);
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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);
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponadto, jeśli chcesz znaleźć wszystkie indeksy łańcucha w ciągu.
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index + guess.length());
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ja też miałem ten problem, dopóki nie wymyśliłem tej metody.
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);
}

Tej metody można użyć do znalezienia indeksów dowolnej flagi o dowolnej długości w ciągu, na przykład:
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);
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Wymyśliłem klasę do dzielenia strun. Na koniec podany jest krótki test.
SplitStringUtils.smartSplitToShorterStrings (String str, int maxLen, int maxParts)
zostanie podzielony spacjami bez podziału na słowa, jeśli to możliwe, a jeśli nie, zostanie podzielony według indeksów zgodnie z maxLen.
Inne metody służące do kontrolowania sposobu podziału:
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;
}
}

Prosty kod testowy:
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();
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To jest rozwiązanie 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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Można to zrobić, wykonując iterację po
myString
i przesuwając parametr
fromIndex
do
indexOf ()
:
int currentIndex = 0; while ( myString.indexOf( mySubstring,
currentIndex) >= 0) { System.out.println(currentIndex); currentIndex++;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Spróbuj tego
String str = "helloslkhellodjladfjhello";
String findStr = "hello";System.out.println(StringUtils.countMatches(str, findStr));

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się