Eu tenho a corda
a.b.c.d
Quero contar as ocorrências de '.' de uma maneira idiomática, preferencialmente de uma linha.
(Anteriormente, eu havia expressado essa restrição como "sem loop", caso você esteja se perguntando por que todo mundo está tentando responder sem usar um loop).
Respostas:
Meu 'one-liner idiomático' para isso é:
Por que você mesmo escrever quando já está em comum ?
O oneliner do Spring Framework para isso é:
fonte
int count = CharMatcher.is('.').countIn("a.b.c.d");
... Conforme respondida por dogbane em uma pergunta duplicada.Que tal agora. Ele não usa regexp por baixo, portanto deve ser mais rápido que algumas das outras soluções e não usará um loop.
fonte
Resuma outra resposta e o que eu sei de todas as maneiras de fazer isso usando uma única linha:
1) Usando o Apache Commons
2) Usando o Spring Framework
3) Usando substituir
4) Usando replaceAll (caso 1)
5) Usando replaceAll (caso 2)
6) Usando split
7) Usando Java8 (caso 1)
8) Usando Java8 (caso 2), pode ser melhor para unicode do que para o caso 1
9) Usando StringTokenizer
Do comentário : Tenha cuidado com o StringTokenizer, pois abcd funcionará, mas para um ... bc ... d ou ... abcd ou a .... b ...... c ..... d ... ou etc. não funcionará. Apenas conta para. entre caracteres apenas uma vez
Mais informações no github
Teste de desempenho (usando JMH , mode = AverageTime, com
0.010
melhor pontuação0.351
):fonte
"1🚲2🚲3 has 2".codePoints().filter((c) -> c == "🚲".codePointAt(0)).count()
Mais cedo ou mais tarde, algo precisa se repetir. É muito mais simples escrever o loop (muito simples) do que usar algo como o
split
que é muito mais poderoso do que você precisa.Por todos os meios, encapsule o loop em um método separado, por exemplo
Então você não precisa ter o loop no seu código principal - mas o loop precisa estar em algum lugar.
fonte
length()
exterior chamada do loop poderia fazer desempenho pior , como mencionado por @ShuggyCoUk alguns comentários acima.Tive uma ideia parecida com a de Mladen, mas o oposto ...
fonte
replaceAll()
elength()
. Bem, se não é visível, não existe; o)ReplaceAll (".") Substituiria todos os caracteres.
A solução da PhiLho usa ReplaceAll ("[^.]", ""), Que não precisa ser escapado, pois [.] Representa o caractere 'ponto', não 'qualquer caractere'.
fonte
Minha solução 'idiomática de uma linha':
Não faço ideia por que uma solução que usa StringUtils é aceita.
fonte
fonte
Um exemplo mais curto é
fonte
aqui está uma solução sem loop:
bem, existe um loop, mas é invisível :-)
- Yonatan
fonte
Não gosto da idéia de alocar uma nova string para esse fim. E como a string já possui uma matriz de caracteres na parte de trás, onde armazena seu valor, String.charAt () é praticamente gratuito.
faz o truque, sem alocações adicionais que precisam de coleta, em 1 linha ou menos, apenas com J2SE.
fonte
charAt
itera através de pontos de código de 16 bits, não caracteres! Achar
em Java não é um caractere. Portanto, essa resposta implica que não deve haver símbolo Unicode com um substituto alto igual ao ponto de código dedelim
. Não tenho certeza se está correto para o ponto, mas em geral pode não estar correto.Ok, inspirado na solução de Yonatan, aqui está um que é puramente recursivo - os únicos métodos de biblioteca usados são
length()
echarAt()
, nenhum dos quais faz loop:Se a recursão conta como loop depende de qual definição exata você usa, mas provavelmente é o mais próximo possível.
Não sei se a maioria das JVMs faz recursão de cauda atualmente ... se não, você obterá o estouro de pilha de mesmo nome para seqüências longas apropriadas, é claro.
fonte
Inspirado por Jon Skeet, uma versão sem loop que não estraga sua pilha. Também é um ponto de partida útil se você deseja usar a estrutura de junção de forquilha.
(Isenção de responsabilidade: não testado, não compilado, não sensato.)
Talvez a melhor (sem suporte a um par substituto) de thread único:
fonte
Não tenho certeza sobre a eficiência disso, mas é o código mais curto que eu poderia escrever sem trazer bibliotecas de terceiros:
fonte
return (content.split(target, -1).length - 1);
. Por padrão, as ocorrências no final da cadeia de caracteres são omitidas na matriz resultante de split (). Veja o DokuCom java-8você também pode usar fluxos para conseguir isso. Obviamente, há uma iteração nos bastidores, mas você não precisa escrevê-la explicitamente!
fonte
.codePoints()
vez de.chars()
suportaria qualquer valor Unicode (incluindo aqueles que requerem pares substitutos)Também é possível usar o reduzir no Java 8 para resolver esse problema:
Resultado:
fonte
Amostra completa:
Ligar:
fonte
A maneira mais simples de obter a resposta é a seguinte:
fonte
Caso esteja usando o Spring framework, você também pode usar a classe "StringUtils". O método seria "countOccurrencesOf".
fonte
Você pode usar a
split()
função em apenas um código de linhafonte
limit
está definido como zero nesta chamada de método de divisão sobrecarregada. Um exemplo:"1##2#3#####".split("#")
produzirá apenas uma matriz de tamanho 4 ([0:"1";1:""; 2:"2"; 3:"3"]
) em vez de tamanho 9 ([0:"1"; 1:""; 2:"2"; 3:"3"; 4:""; 5:""; 6:""; 7:""; 8:""]
).fonte
fonte
Embora os métodos possam ocultá-lo, não há como contar sem um loop (ou recursão). Você deseja usar um char [] por razões de desempenho.
O uso de replaceAll (ou seja, RE) não parece o melhor caminho a percorrer.
fonte
Bem, com uma tarefa bem parecida, me deparei com este Tópico. Eu não vi nenhuma restrição de linguagem de programação e como o groovy é executado em um java vm: Aqui está como eu consegui resolver meu problema usando o Groovy.
feito.
fonte
Uma solução muito mais fácil seria dividir a string com base no caractere com o qual você está combinando.
Por exemplo,
int getOccurences(String characters, String string) { String[] words = string.split(characters); return words.length - 1; }
Isso retornará 4 no caso de:
getOccurences("o", "something about a quick brown fox");
fonte
Em algum lugar do código, algo precisa fazer um loop. A única maneira de contornar isso é um desenrolar completo do loop:
... etc, mas é você quem executa o loop manualmente no editor de código-fonte - em vez do computador que o executará. Veja o pseudocódigo:
fonte
Aqui está uma solução de recursão de estilo um pouco diferente:
fonte
Por que não apenas dividir o caractere e obter o comprimento da matriz resultante. o comprimento da matriz sempre será o número de instâncias + 1. Certo?
fonte
O seguinte código-fonte não fornecerá nenhuma ocorrência de uma determinada sequência em uma palavra inserida pelo usuário: -
fonte
fonte