Odpowiedzi:
To powinno wydrukować listę pozycji bez -1
na koniec, że rozwiązanie Petera Lawrey za nie miałem.
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 for
pętlę:
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ższy niż pojedynczy znak, analizując guess
łańcuch, można wykonać pętlę word
szybciej niż powyższe pętle. Wzorcem dla takiego podejścia jest algorytm Boyera-Moore'a . Wydaje się jednak, że nie istnieją warunki, które sprzyjałyby zastosowaniu takiego podejścia.]
Spróbuj wykonać następujące czynności (co nie powoduje teraz wypisania -1 na końcu!)
int index = word.indexOf(guess);
while(index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index+1);
}
indexOf
zwraca -1, gdy znak nie zostanie znaleziony.
-1
na końcu, jest to, że do
pętla wykonuje treść, a następnie odkrywa to index == -1
w zakończeniu while
.
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 zostałby użyty w następujący sposób:
for(Integer i : list){
System.out.println(i);
}
Lub jako tablica:
list.toArray();
W Javie9 można skorzystać z iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)
:
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);
Można to zrobić w funkcjonalny sposób w Javie 9 używając 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 nowej nowej metody do CharSequence
interfejsu API 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]
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)
się nie skompiluje. : P
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);
Ponadto, jeśli chcesz znaleźć wszystkie indeksy String w String.
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index + guess.length());
}
guess
było "aba"
i word
było "ababa"
, nie jest jasne, czy guess
zdarzyło się to raz czy dwa razy word
. (To znaczy, jasne jest, że można znaleźć guess
początek w dwóch różnych pozycjach, ale ponieważ wystąpienia nakładają się, nie jest jasne, czy należy je policzyć.) W tej odpowiedzi przyjęto pogląd, że nakładające się wystąpienia nie są liczone jako odrębne. Oczywiście, ponieważ sformułowanie OP zdecydowanie sugeruje, że guess
zawsze będzie miał długość 1, nie ma dwuznaczności.
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);
}
}
Wymyślona przeze mnie klasa do dzielenia strun. Na końcu znajduje się krótki test.
SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts)
jeśli to możliwe, podzieli spacje bez łamania słów, a jeśli nie, podzieli według indeksów zgodnie z maxLen.
Inne metody kontroli 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();
}
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;
}
Można to zrobić poprzez iterację myString
i zmianę fromIndex
parametrów w indexOf()
:
int currentIndex = 0;
while (
myString.indexOf(
mySubstring,
currentIndex) >= 0) {
System.out.println(currentIndex);
currentIndex++;
}
mySubstring
, niezależnie od tego, czy mySubstring
można go znaleźć na każdej pozycji. Zupełnie nie to, czego chciał OP ...
Spróbuj tego
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(StringUtils.countMatches(str, findStr));