J'ai la ficelle
a.b.c.d
Je veux compter les occurrences de '.' de manière idiomatique, de préférence un one-liner.
(Auparavant, j'avais exprimé cette contrainte comme "sans boucle", au cas où vous vous demanderiez pourquoi tout le monde essaie de répondre sans utiliser de boucle).
Mon "one-liner" idiomatique pour cela est:
int count = StringUtils.countMatches("a.b.c.d", ".");
Pourquoi l'écrire vous-même quand il est déjà dans commons lang ?
Oneliner de Spring Framework pour cela est:
int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
Que dis-tu de ça. Il n'utilise pas l'expression rationnelle sous-jacente, il devrait donc être plus rapide que d'autres solutions et ne pas utiliser de boucle.
int count = line.length() - line.replace(".", "").length();
Résumez une autre réponse et ce que je connais de toutes les façons de le faire en utilisant un seul support:
String testString = "a.b.c.d";
1) Utiliser Apache Commons
int Apache = StringUtils.countMatches(testString, ".");
System.out.println("Apache = " + Apache);
2) Utilisation de Spring Framework
int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);
3) Utiliser remplacer
int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);
4) Utiliser replaceAll (cas 1)
int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);
5) Utiliser replaceAll (cas 2)
int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);
6) Utilisation de split
int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);
7) Utiliser Java8 (cas 1)
long Java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("Java8 = " + Java8);
8) Utiliser Java8 (cas 2) peut être meilleur pour unicode que pour le cas 1
long Java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("Java8 (second case) = " + Java8Case2);
9) Utiliser StringTokenizer
int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);
Du commentaire : Attention au StringTokenizer, pour abcd cela fonctionnera mais pour un ... bc ... d ou ... abcd ou un .... b ...... c ..... d ... ou etc. cela ne fonctionnera pas. Cela comptera pour. entre les personnages juste une fois
Plus d'infos dans github
Test de performance (avec JMH , mode = Temps moyen, score 0.010
meilleur que 0.351
):
Benchmark Mode Cnt Score Error Units
1. countMatches avgt 5 0.010 ± 0.001 us/op
2. countOccurrencesOf avgt 5 0.010 ± 0.001 us/op
3. stringTokenizer avgt 5 0.028 ± 0.002 us/op
4. Java8_1 avgt 5 0.077 ± 0.005 us/op
5. Java8_2 avgt 5 0.078 ± 0.003 us/op
6. split avgt 5 0.137 ± 0.009 us/op
7. replaceAll_2 avgt 5 0.302 ± 0.047 us/op
8. replace avgt 5 0.303 ± 0.034 us/op
9. replaceAll_1 avgt 5 0.351 ± 0.045 us/op
Tôt ou tard, quelque chose doit boucler. C'est beaucoup plus simple pour vous d'écrire la boucle (très simple) que d'utiliser quelque chose comme split
qui est beaucoup plus puissant que nécessaire.
Bien entendu, encapsulez la boucle dans un procédé séparé, par ex.
public static int countOccurrences(String haystack, char needle)
{
int count = 0;
for (int i=0; i < haystack.length(); i++)
{
if (haystack.charAt(i) == needle)
{
count++;
}
}
return count;
}
Dans ce cas, vous n'avez pas besoin de la boucle dans votre code principal - mais la boucle doit être présente quelque part.
J'ai eu une idée similaire à Mladen, mais l'inverse ...
String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();
ReplaceAll (".") Remplacerait tous les caractères.
La solution de PhiLho utilise ReplaceAll ("[^.]", ""), Qui n'a pas besoin d'être échappé, car [.] Représente le caractère "point", pas "n'importe quel caractère".
Ma solution "one-liner" idiomatique:
int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();
Vous ne savez pas pourquoi une solution utilisant StringUtils est acceptée.
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
Un exemple plus court est
String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
voici une solution sans boucle:
public static int countOccurrences(String haystack, char needle, int i){
return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}
System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));
eh bien, il y a une boucle, mais c'est invisible :-)
- Yonatan
Je n'aime pas l'idée d'attribuer une nouvelle chaîne à cette fin. Et comme la chaîne a déjà un tableau de caractères à l'arrière où elle stocke sa valeur, String.charAt () est pratiquement libre.
for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))
fait l'affaire, sans attributions supplémentaires nécessitant une collecte, en 1 ligne ou moins, avec uniquement J2SE.
Ok, inspiré de la solution de Yonatan, en voici une qui est purement récursive - les seules méthodes de bibliothèque utilisées sont length()
et charAt()
, qui ne font aucune boucle:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int index)
{
if (index >= haystack.length())
{
return 0;
}
int contribution = haystack.charAt(index) == needle ? 1 : 0;
return contribution + countOccurrences(haystack, needle, index+1);
}
Que la récursivité compte ou non en boucle dépend de la définition exacte que vous utilisez, mais elle est probablement aussi proche que possible.
Je ne sais pas si la plupart des machines virtuelles font la récursion de la queue ces jours-ci ... sinon, vous obtiendrez le débordement de pile éponyme pour des chaînes suffisamment longues, bien sûr.
Inspiré de Jon Skeet, une version sans boucle qui ne fera pas sauter votre pile. Point de départ également utile si vous souhaitez utiliser le framework fork-join.
public static int countOccurrences(CharSequeunce haystack, char needle) {
return countOccurrences(haystack, needle, 0, haystack.length);
}
// Alternatively String.substring/subsequence use to be relatively efficient
// on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
CharSequence haystack, char needle, int start, int end
) {
if (start == end) {
return 0;
} else if (start+1 == end) {
return haystack.charAt(start) == needle ? 1 : 0;
} else {
int mid = (end+start)>>>1; // Watch for integer overflow...
return
countOccurrences(haystack, needle, start, mid) +
countOccurrences(haystack, needle, mid, end);
}
}
(Avertissement: non testé, non compilé, non raisonnable.)
Peut-être le meilleur moyen de l'écrire (avec un seul thread, sans support de paire de substitution):
public static int countOccurrences(String haystack, char needle) {
int count = 0;
for (char c : haystack.toCharArray()) {
if (c == needle) {
++count;
}
}
return count;
}
Pas sûr de l'efficacité de ceci, mais c'est le code le plus court que j'ai pu écrire sans faire appel à des bibliothèques tierces:
public static int numberOf(String target, String content)
{
return (content.split(target).length - 1);
}
Avec Java-8 , vous pouvez également utiliser des flux pour y parvenir. Évidemment, il y a une itération dans les coulisses, mais vous n'avez pas à l'écrire explicitement!
public static long countOccurences(String s, char c){
return s.chars().filter(ch -> ch == c).count();
}
countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
Il est également possible d'utiliser une réduction dans Java 8 pour résoudre ce problème:
int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);
Sortie:
3
échantillon complet:
public class CharacterCounter
{
public static int countOccurrences(String find, String string)
{
int count = 0;
int indexOf = 0;
while (indexOf > -1)
{
indexOf = string.indexOf(find, indexOf + 1);
if (indexOf > -1)
count++;
}
return count;
}
}
Appel:
int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
Le moyen le plus simple d'obtenir la réponse est le suivant:
public static void main(String[] args) {
String string = "a.b.c.d";
String []splitArray = string.split("\\.",-1);
System.out.println("No of . chars is : " + (splitArray.length-1));
}
Si vous utilisez un framework Spring, vous pouvez également utiliser la classe "StringUtils". La méthode serait "countOccurrencesOf".
Vous pouvez utiliser la fonction split()
en un seul code de ligne
int noOccurence=string.split("#",-1).length-1;
import Java.util.Scanner;
class apples {
public static void main(String args[]) {
Scanner bucky = new Scanner(System.in);
String hello = bucky.nextLine();
int charCount = hello.length() - hello.replaceAll("e", "").length();
System.out.println(charCount);
}
}// COUNTS NUMBER OF "e" CHAR´s within any string input
public static int countOccurrences(String container, String content){
int lastIndex, currIndex = 0, occurrences = 0;
while(true) {
lastIndex = container.indexOf(content, currIndex);
if(lastIndex == -1) {
break;
}
currIndex = lastIndex + content.length();
occurrences++;
}
return occurrences;
}
Bien que les méthodes puissent le masquer, il n’ya aucun moyen de compter sans une boucle (ou une récursion). Vous souhaitez cependant utiliser un caractère [] pour des raisons de performances.
public static int count( final String s, final char c ) {
final char[] chars = s.toCharArray();
int count = 0;
for(int i=0; i<chars.length; i++) {
if (chars[i] == c) {
count++;
}
}
return count;
}
Utiliser replaceAll (c'est-à-dire RE) ne semble pas être la meilleure solution.
Pourquoi ne pas simplement diviser sur le caractère et ensuite obtenir la longueur du tableau résultant. la longueur du tableau sera toujours le nombre d'instances + 1. Pas vrai?
Eh bien, avec une tâche assez similaire, je suis tombé sur ce fil. Je n'ai vu aucune restriction de langage de programmation et, depuis que groovy est exécuté sur un Java vm: Voici comment j'ai pu résoudre mon problème en utilisant Groovy.
"a.b.c.".count(".")
terminé.
Utilisation de Eclipse Collections
int count = CharAdapter.adapt("a.b.c.d").count(c -> c == '.');
Si vous devez compter plus d'un caractère, vous pouvez utiliser un CharBag
comme suit:
CharBag bag = CharAdapter.adapt("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');
Remarque: je suis un partisan des collections Eclipse.
int count = (line.length() - line.replace("str", "").length())/"str".length();
Voici une solution de récursion de style légèrement différente:
public static int countOccurrences(String haystack, char needle)
{
return countOccurrences(haystack, needle, 0);
}
private static int countOccurrences(String haystack, char needle, int accumulator)
{
if (haystack.length() == 0) return accumulator;
return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}
Le code source suivant ne vous donnera pas le nombre d'occurrences d'une chaîne donnée dans un mot entré par l'utilisateur: -
import Java.util.Scanner;
public class CountingOccurences {
public static void main(String[] args) {
Scanner inp= new Scanner(System.in);
String str;
char ch;
int count=0;
System.out.println("Enter the string:");
str=inp.nextLine();
while(str.length()>0)
{
ch=str.charAt(0);
int i=0;
while(str.charAt(i)==ch)
{
count =count+i;
i++;
}
str.substring(count);
System.out.println(ch);
System.out.println(count);
}
}
}
Quelque part dans le code, quelque chose doit boucler. Le seul moyen de contourner ce problème est de dérouler complètement la boucle:
int numDots = 0;
if (s.charAt(0) == '.') {
numDots++;
}
if (s.charAt(1) == '.') {
numDots++;
}
if (s.charAt(2) == '.') {
numDots++;
}
... etc., mais c'est vous qui faites la boucle manuellement dans l'éditeur de code source, au lieu de l'ordinateur qui l'exécutera. Voir le pseudocode:
create a project
position = 0
while (not end of string) {
write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to
Essayez cette méthode:
StringTokenizer stOR = new StringTokenizer(someExpression, "||");
int orCount = stOR.countTokens()-1;
String[] parts = text.split(".");
int occurances = parts.length - 1;
" It's a great day at O.S.G. Dallas! "
-- Famous Last Words
Eh bien, il s'agit de connaître votre Java, en particulier votre compréhension de base des classes de collection déjà disponibles en Java. Si vous parcourez l'intégralité de l'article, il y a à peu près tout, sauf l'explication de Stephen Hawking sur l'origine de l'univers, le livre de poche de Darwin sur Evolution et la sélection de casting de Gene Roddenberry dans Star Trek pour expliquer pourquoi ils sont allés avec William Shatner. ceci rapidement et facilement ...
... dois-je en dire plus?
Je vois beaucoup de trucs et de telles utilisations. Maintenant, je ne suis pas contre les belles astuces mais personnellement j'aime appeler simplement les méthodes qui sont signifiées pour faire le travail, alors j'ai créé encore une autre répondre.
Notez que si les performances posent problème, utilisez plutôt réponse de Jon Skeet . Celui-ci est un peu plus généralisé et donc légèrement plus lisible à mon avis (et bien sûr, réutilisable pour les chaînes et les patterns).
public static int countOccurances(char c, String input) {
return countOccurancesOfPattern(Pattern.quote(Character.toString(c)), input);
}
public static int countOccurances(String s, String input) {
return countOccurancesOfPattern(Pattern.quote(s), input);
}
public static int countOccurancesOfPattern(String pattern, String input) {
Matcher m = Pattern.compile(pattern).matcher(input);
int count = 0;
while (m.find()) {
count++;
}
return count;
}
Pourquoi essayez-vous d'éviter la boucle? Je veux dire que vous ne pouvez pas compter les points "numberOf" sans vérifier chaque caractère de la chaîne, et si vous appelez une fonction, elle se mettra en boucle. En d’autres termes, String.replace doit effectuer une boucle pour vérifier si la chaîne apparaît afin de pouvoir remplacer chaque occurrence.
Si vous essayez de réduire l'utilisation des ressources, vous ne le ferez pas comme cela, car vous créez une nouvelle chaîne simplement pour compter les points.
Maintenant, si nous parlons de la méthode récursive "entrer le code ici", quelqu'un a dit que cela échouerait à cause d'une exception OutOfMemmoryException, je pense qu'il a oublié StackOverflowException.
Donc ma méthode serait comme ça (je sais que c'est comme les autres mais, ce problème nécessite la boucle):
public static int numberOf(String str,int c) {
int res=0;
if(str==null)
return res;
for(int i=0;i<str.length();i++)
if(c==str.charAt(i))
res++;
return res;
}
public static int countSubstring(String subStr, String str) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.substring(i).startsWith(subStr)) {
count++;
}
}
return count;
}
En utilisant Java 8 et un HashMap sans aucune bibliothèque pour compter tous les différents caractères:
private static void countChars(String string) {
HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
string.chars().forEach(letter -> hm.put(letter, (hm.containsKey(letter) ? hm.get(letter) : 0) + 1));
hm.forEach((c, i) -> System.out.println(((char)c.intValue()) + ":" + i));
}
Si vous voulez compter le non. du même caractère dans une chaîne 'Selenium' ou si vous souhaitez imprimer les caractères uniques de la chaîne 'Selenium'.
public class Count_Characters_In_String{
public static void main(String []args){
String s = "Selenium";
System.out.println(s);
int counter;
String g = "";
for( int i=0; i<s.length(); i++ ) {
if(g.indexOf(s.charAt(i)) == - 1){
g=g+s.charAt(i);
}
}
System.out.println(g + " ");
for( int i=0; i<g.length(); i++ ) {
System.out.print(",");
System.out.print(s.charAt(i)+ " : ");
counter=0;
for( int j=0; j<s.length(); j++ ) {
if( g.charAt(i) == s.charAt(j) ) {
counter=counter+1;
}
}
System.out.print(counter);
}
}
}
/ ******************** OUTPUT ********************* /
Sélénium
SELNIUM
S: 1, E: 2, L: 1, E: 1, N: 1, I: 1, U: 1.
Essayez ce code:
package com.Java.test;
import Java.util.HashMap;
import Java.util.Map;
public class TestCuntstring {
public static void main(String[] args) {
String name = "Bissssmmayaa";
char[] ar = new char[name.length()];
for (int i = 0; i < name.length(); i++) {
ar[i] = name.charAt(i);
}
Map<Character, String> map=new HashMap<Character, String>();
for (int i = 0; i < ar.length; i++) {
int count=0;
for (int j = 0; j < ar.length; j++) {
if(ar[i]==ar[j]){
count++;
}
}
map.put(ar[i], count+" no of times");
}
System.out.println(map);
}
}
Qu'en est-il de l'algo récursif ci-dessous.Il s'agit également du temps linéaire.
import Java.lang.*;
import Java.util.*;
class longestSubstr{
public static void main(String[] args){
String s="ABDEFGABEF";
int ans=calc(s);
System.out.println("Max nonrepeating seq= "+ans);
}
public static int calc(String s)
{//s.s
int n=s.length();
int max=1;
if(n==1)
return 1;
if(n==2)
{
if(s.charAt(0)==s.charAt(1)) return 1;
else return 2;
}
String s1=s;
String a=s.charAt(n-1)+"";
s1=s1.replace(a,"");
// System.out.println(s+" "+(n-2)+" "+s.substring(0,n-1));
max=Math.max(calc(s.substring(0,n-1)),(calc(s1)+1));
return max;
}
}
</i>