Respostas:
Isso deve imprimir a lista de posições sem a -1
no final que a solução de Peter Lawrey tem tido.
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index + 1);
}
Também pode ser feito em for
loop:
for (int index = word.indexOf(guess);
index >= 0;
index = word.indexOf(guess, index + 1))
{
System.out.println(index);
}
[Nota: se guess
pode ser mais longo do que um único caractere, então é possível, analisando a guess
string, fazer um loop word
mais rápido do que os loops acima. O benchmark para tal abordagem é o algoritmo Boyer-Moore . No entanto, as condições que favorecem o uso de tal abordagem não parecem estar presentes.]
Tente o seguinte (que não imprime -1 no final agora!)
int index = word.indexOf(guess);
while(index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index+1);
}
indexOf
retorna -1 quando o caractere não é encontrado.
-1
no final é que o do
loop executa o corpo e, em seguida, descobre isso index == -1
na finalização 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);
}
}
O resultado seria usado assim:
for(Integer i : list){
System.out.println(i);
}
Ou como uma matriz:
list.toArray();
Com o Java9, pode-se fazer uso do iterate(int seed, IntPredicate hasNext,IntUnaryOperator next)
seguinte: -
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);
Isso pode ser feito de maneira funcional com Java 9, usando expressão regular:
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
);
Esta é a solução Kotlin para adicionar essa lógica como um novo método à CharSequence
API usando o método de extensão:
// 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)
não compila. : 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);
Além disso, se você quiser encontrar todos os índices de uma String em uma String.
int index = word.indexOf(guess);
while (index >= 0) {
System.out.println(index);
index = word.indexOf(guess, index + guess.length());
}
guess
foi "aba"
e word
foi "ababa"
, não está claro se guess
ocorre uma ou duas vezes em word
. (Quer dizer, é claro que pode-se encontrar guess
começando em duas posições distintas, mas como as ocorrências se sobrepõem, não está claro se ambas devem ser contadas.) Essa resposta considera que ocorrências sobrepostas não são contadas como distintas. Claro, uma vez que o texto de OP sugere fortemente que guess
sempre terá comprimento 1, a ambigüidade não surge.
Eu também tive esse problema, até que inventei esse método.
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);
}
Este método pode ser usado para encontrar índices de qualquer sinalizador de qualquer comprimento em uma string, por exemplo:
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);
}
}
Uma classe para dividir cordas que eu criei. Um breve teste é fornecido no final.
SplitStringUtils.smartSplitToShorterStrings(String str, int maxLen, int maxParts)
será dividido por espaços sem quebrar palavras, se possível, e se não, será dividido por índices de acordo com maxLen.
Outros métodos fornecidos para controlar como é dividido: 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;
}
}
Código de teste simples:
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();
}
Esta é uma solução 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;
}
Isso pode ser feito iterando myString
e mudando o fromIndex
parâmetro em indexOf()
:
int currentIndex = 0;
while (
myString.indexOf(
mySubstring,
currentIndex) >= 0) {
System.out.println(currentIndex);
currentIndex++;
}
mySubstring
, independentemente de mySubstring
poder ser encontrado em cada posição. Nem um pouco o que a OP queria ..
Tente isto
String str = "helloslkhellodjladfjhello";
String findStr = "hello";
System.out.println(StringUtils.countMatches(str, findStr));