J'ai une chaîne et je veux compter la survenue de toutes les lettres et numéros et que vous souhaitez créer un graphique afin que je puisse voir l'occurrence graphiquement.
Donc, par exemple: p> ma façon de penser: p> Je pense qu'il y a deux façons de compter les personnages. Je peux utiliser l'utilisation de la méthode Par exemple: p> Cependant, j'ai plusieurs problèmes avec cette approche: p> Je ne demande pas une réponse définie ici, je suis juste à la recherche de bonnes directions, car je suis coincé. p> p>
Charat () code> ou TOCHARARRAY () CODE> et boucle via la chaîne ou la matrice et compter les lettres. p>
acounter code> via zcounter code> plus 0counter code> via 9counter code> li>
12 Réponses :
Il n'y a pas besoin de faire un Vous savez quels caractères sont suivis à l'avance, donc vous peut utiliser un tableau. strong> p> Je veux compter la survenue de toutes les lettres et numéros p>
blockQuote> Créez une chaîne de caractères que vous suivez, puis initialisez un tableau. p> puis vous pouvez tous les imprimer avec ceci: p > Si vous n'êtes pas à l'aise avec la nouvelle chaîne Voici certaines choses à prendre en compte lorsqu'ils ont décidé comment résoudre ce problème. P> hashtable / hashmap / hashmet code> pour cela. em>
(nouveau char [Nombre [i]]). Remplacez ('\ 0', '*')) Code> Bit, alors vous pouvez utiliser un StringBuilder CODE> pour créer la chaîne d'astérisque code> avant d'essayer de le sortir. Vous pouvez voir @mike em> strud> s selon l'exemple ci-dessous pour un bon exemple de cela. P> sorties h3>
Considérations h3>
J'ai ajouté une autre approche ... une tropillasse. Si j'ai le temps, je vais créer un troisième avec moins de lignes de code que possible.
Bien qu'il soit vrai que vous n'avez pas besoin de hashmap code>, il s'agit d'une structure de données adaptée à la tâche (bien, en réalité, une multiset est, mais nous n'avons pas celui-ci dans les bibliothèques standard Java) . Votre approche fonctionne pour la plupart i> des intrants bien, mais si je vis à vivre dans un pays qui a des personnages spéciaux comme "ěščřžýáé"? Et si j'oublie certains ("ůůňťď")? En outre, invoquer indexofof () code> sur chaque itération fonctionne, mais je suis curieux de ses performances avec des chaînes d'entrée LOOOOOOONG. Tous, alors que cela fonctionne, je ne dirais pas que c'est un moyen d'aller avec les approches modernes Java existant. Ce sont les années 1990 qui appelle à nouveau
@Slanec indexof code> est appelé sur la carte des caractères suivis et non sur la chaîne d'entrée elle-même. En outre, lisez ma section Considérations b> et vous verrez que les autres points que vous avez faits sont déjà dans ma réponse.
@crush je me sens mal et je suis désolé. Je dois admettre honteusement que je n'ai pas lu cette section. Cela raconte en effet toute l'histoire. Et oui, je suis au courant de l'index de () code> d'utilisation et je serais toujours inquiet. Il est toujours linéaire sondage et à petite échelle, ce n'est rien, si le tableau code> code> était plus long et que nous avions beaucoup d'informations, cela pourrait être notable. C'est une bonne approche à des fins éducatives, cependant, oui.
@Slanec pas besoin d'être honteux! Je le fais tout le temps ;)
Je dois contrer votre première considération. Un tableau fonctionnera toujours si Char code> S est considéré, car ils ont une taille fixe de 2 octets.
@mike Cela ne fonctionnerait pas parce que vous ne savez pas à quel point pour faire le tableau initialement. tout code> signifie que vous ne savez pas ce que tous les caractères que vous suivez, vous devez donc suivre n'importe quel personnage rencontré, vous devez donc allouer la matrice à une taille énorme pouvant aller gaspiller. , ou vous auriez besoin de réaffecter le tableau car il grandit - d'une bonne affaire d'utiliser une structure de données comme un hashmap code>.
Je l'ai fait ici: Stackoverflow.com/a/18787187/1809463 depuis qu'un caractère a une taille fixe de 16 bits, il y a 2 ^ 16 = 65536 Affectations possibles pour un Char code>.
@ Mike Droite - et la plupart de ces éléments sont gaspillés car 90% d'entre eux ne seront pas présents dans la chaîne d'entrée.
@crush il ne nécessiterait que 256kb de mémoire. Pas une grosse affaire sur les machines modernes. Mais oui, il restait encore beaucoup d'INT inutilisé à gauche.
Créez une haquetable et passez par la chaîne, ajoutez chaque fois le caractère actuel de la haquetable
C'est une approche propre. N'oubliez pas d'aborder l'impression de la sortie (la question des astérisques) avec votre réponse!
@crush a ajouté que. Nice nom BTW
hashtable code> et énumération code> - quelle année est-ce? :) (le code moderne utiliserait hashmap code> et itérateur code>)
Utilisez un tableau pour stocker les comptoirs. Vous pouvez utiliser un caractère directement en tant qu'index de tableau, de sorte que vous n'avez pas besoin de logique complexe. P>
Imprimer un nombre donné d'astérisques, une bouclette est la solution la plus simple. P>
Le moyen le plus simple serait ce que @crush a fait nouvelle chaîne (nouveau char [Nombre [I]]). Remplacer ('\ 0', '*')) code>
Ce qui est "plus facile" est discutable - créer une matrice pleine de caractères nul, créant une chaîne de ce tableau et créer une autre chaîne dans laquelle chaque caractère nul est remplacé par un astérisque n'est pas trivial et inefficace. C'est un tour soigné cependant.
@Joni plus efficace utiliserait un StringBuilder, mais vous vous retrouvez avec au moins 2-3 autres lignes de code en fonction de la façon dont vous l'avez écrites. La concaténation de la chaîne dans A pour la boucle sera remarquablement pire, cependant. Je n'ai pas votre commentaire à ce sujet en train d'être non trivial code>. Cela me semble assez trivial.
@crush j'ai utilisé un stringbuilder code> dans la réponse que j'ai posté. ... Mais j'ai toujours eu une fable pour un one-liners: D ... Je pense qu'avec non trivial, il voulait dire qu'il est un type de piratage et non la première approche qui vient à l'esprit.
Si vous souhaitez imprimer un nombre donné d'astérisques, la première chose qui vous vient à l'esprit est une boucle qui les imprime un par un. Construire une chaîne est un pas en avant dans l'échelle d'abstraction ...
D'accord. Je n'ai pas assimilé non trivial avec ça, mais je comprends ce que vous voulez dire maintenant. StringBuilder Code> est peut-être la meilleure solution pour l'impression n code> astérisques, comme @Mike le fait dans son exemple.
Voici quelques astuces pour vous aider à démarrer: p>
n'utilise pas une variable séparée pour chaque compteur. Utilisez un tableau (ou un type de collecte ... Si vous avez appris à ce sujet ...). P> LI>
Vous pouvez utiliser un caractère comme indice de tableau. P> li>
accumuler tous les comptes avant de commencer à imprimer quelque chose. p> li> ol>
@Mike Parfois, le code fait une meilleure explication. =) C'est une belle sommation de ma mise en œuvre ci-dessous, cependant. C'est abstrait! +1
au lieu de boucler une fois pour calculer la quantité et en boucle une seconde fois pour imprimer les astérisques, vous pouvez utiliser une autre approche: puis, chaque fois que vous iTeriez, vous vérifiez si votre La carte contient des données pour le caractère et, si ce n'est pas le cas, vous l'initialisez. En pseudocode: p> Si vous avez besoin de la quantité d'astérisques en tant que nombre, vous pouvez toujours obtenir la taille de ce comme une amélioration, en tenant compte des commentaires que j'ai partagés avec @crush, deux modifications peuvent améliorer la logique: P > C'est à la question d'ajouter cette affaire supplémentaire, s'il y a une place (et une connaissance) suffisamment pour justifier leur utilisation. P> P> chaîne code> (supposant que vous ne donez pas 'T mettre des espaces blanchisseurs). p>
mise à jour h3>
stringbuilder code> au lieu de chaîne code>: em> éviter la création inutile de littéraux. li>
Treemap code> au lieu de hashmap code>: em> Il donnerait la commande appropriée à la carte, permettant une impression triée de son contenu. LI >
ul>
N'oubliez pas de mettre à jour le nombre d'occurrences dans la chaîne code> aussi. N'oubliez pas que le format est a (3) *** code> vous devez également mettre à jour le compte. En fin de compte, vous devez toujours itérer sur la carte pour afficher chaque chaîne code>.
@crush Le compte est la taille de la chaîne stockée. Et en effet, vous devez itération sur la carte, mais vous avez toutes les informations là-bas. C'est une seule itération d'afficher les résultats à la fin.
Oh, j'ai manqué que vous étiez simplement en train de stocker une chaîne d'astérisques. Donc, à la fin, vous auriez quelque chose comme string.format ("% s (% d)% s", entrée.getkey (), entrée.gevalue (). Longueur (), entrée.gevalue (), entrée.gevalue () ); code>
@crush, par exemple, oui, si l'OP connaît environ Format de chaîne code>. Sinon, une simple concaténation fonctionne aussi :)
Je pense que votre réponse n'atteignait pas l'attention qu'elle mérite. Par exemple, ma réponse nécessiterait trois boucles, sinon pour le string.replace () code> entreprise (qui est techniquement en boucle en interne). Cette approche ne nécessitera que deux boucles. Je préférerais voir l'utilisation d'un Treemap code> cependant, je pense. Retour à mon array exemple, cependant, un tableau de chaîne code> pourrait accomplir le même résultat, mais les concatenations seraient désagréables car elles créeraient une nouvelle chaîne immuable code> sur chaque boucler.
@crush et moi avons évoqué le vôtre pour cette utilisation intelligente d'index;). En effet, Treemap code> serait un bon diape afin d'imprimer les valeurs avec la commande appropriée, étant donné que le caractère code> est livré avec un comparète code> implémentation. Je dirais que je dirais que l'approche code> string code>, car je ne suis pas tout à fait sûr que l'opération connaît sur stringbuilder code>. Au début, j'avais utilisé des constructeurs au lieu des cordes crus CODE> mais sont allés pour une approche plus simple afin de manifester un certain degré de simplicité, Bot Ces deux points sont une bonne mise à jour.
Divisez-le en deux méthodes b> - une pour créer une chaîne "rangée" donnée un char et une chaîne, et un pour appeler la première méthode pour chacun des 36 caractères alphanumériques. public static String alphNum = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
public static String count(char c, String str) {
String stringToReturn = Character.toString(c);
for(char ch : str.toCharArray()) {
if (ch == c) {
stringToReturn += " *";
}
}
return stringToReturn;
}
public static void countAndPrintAlphNum(String str) {
String stringToTest = str.toUpperCase();
Set<String> rows = new HashSet<String>();
char[] alphNumArray = alphNum.toCharArray();
for(char c : alphNumArray) {
rows.add(count(c, stringToTest));
}
for(String row : rows) {
System.out.println(row);
}
}
public static void main(String[] args) {
countAndPrintAlphNum("Hi There 123!");
}
@crush c'est vrai, oui. En «assurez-vous», je pensais à la programmation de manière défensive (si la chaîne d'alpnum n'est pas dans l'ordre). Bien sûr, d'une autre part, avoir peut-être que la dernière fois est souhaitée et que nous allions donc utiliser un hashset.
Voici une approche d'OOP, qui utilise Stringreader code> et une carte. J'ai utilisé Treemap code>
avoir la sortie triée. public class StringHistogram
{
public static void main(String[] args) throws IOException
{
Scanner sc = new Scanner(System.in);
System.out.print("Please insert string: ");
String s = sc.nextLine();
sc.close();
System.out.println(s);
StringReader r = new StringReader(s);
Map<Character, Integer> histogram = new TreeMap<Character, Integer>();
int c;
while ((c = r.read()) != -1) {
Integer count = histogram.get((char) c);
if (count == null)
count = 0;
histogram.put((char) c, count + 1);
}
r.close();
for (Entry<Character, Integer> entry : histogram.entrySet())
System.out.println(entry.getKey() + " (" + entry.getValue()
+ ") " + createAsterisk(entry.getValue()));
}
private static String createAsterisk(int number) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < number; i++)
sb.append("*");
return sb.toString();
}
}
Depuis que vous êtes nouveau à cela et que vous n'avez pas déjà la solution (qui est l'endroit où tout le monde commence), la réponse droite em> est d'utiliser la structure de données que vous apprenez en classe. p>
Si vous apprenez des cartes p>
Si vous apprenez des tableaux, il existe de grands exemples dans ce fil déjà ex. Réponse du béguin p>
Excellent point. Cela ne devrait tout simplement pas être négligé. Comme il s'agit d'une mission de devoirs, il est important d'appliquer ce que vous apprenez en classe au problème.
Depuis, nous vivons en période d'informatique en nuage et de parallélisme. Voici une autre approche.
public class DistributedHistogram
{
private static final int PORT = 1337;
private static final String LOOPBACK = "127.0.13.37";
public static final byte[] DATA = new byte[] {(byte) 0xFF, (byte) 0xFF};
public static final byte[] STOP = new byte[] {(byte) 0xDE, (byte) 0xAD};
public static void main(String[] args) throws IOException, InterruptedException
{
ExecutorService se = Executors.newSingleThreadExecutor();
se.submit(new Server(PORT, 16));
System.out.print("Please insert string: ");
Scanner s = new Scanner(System.in);
String input = s.nextLine();
s.close();
System.out.println(input);
ExecutorService ce = Executors.newFixedThreadPool(16);
List<Future<Void>> futures = new ArrayList<Future<Void>>();
for (char c : input.toCharArray())
futures.add(ce.submit(new Client(new Character[]{c}, DATA, LOOPBACK, PORT)));
/* wait for the clients to complete before we send stop to server */
for (Future<Void> f : futures)
{
try
{
@SuppressWarnings ("unused")
Void v = f.get();
}
catch (ExecutionException e)
{
//...
}
}
ce.submit(new StopClient(LOOPBACK, PORT)); // sends stop signal
ce.shutdown();
se.shutdown();
}
}
class Client implements Callable<Void>
{
private final Character[] chars;
private final String ip;
private final int port;
private final byte[] type;
public Client(Character[] chars, byte[] type, String ip, int port)
{
this.chars = chars;
this.type = type;
this.ip = ip;
this.port = port;
}
@Override
public Void call() throws Exception
{
Socket s = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
for (Character c : chars) {
out.write(type);
out.writeChar(c);
}
out.flush();
out.close();
s.close();
return null;
}
}
class StopClient extends Client {
public StopClient(String ip, int port)
{
super(new Character[]{' '}, DistributedHistogram.STOP, ip, port);
}
}
class Server implements Callable<Void>
{
private final int port;
private ServerSocket ss;
private final ExecutorService e;
private final ConcurrentHistogram ch = new ConcurrentHistogram();
private final AtomicInteger client = new AtomicInteger();
private AtomicBoolean quit = new AtomicBoolean(false);
public Server(int port, int clients)
{
this.port = port;
this.e = Executors.newFixedThreadPool(clients);
}
public ConcurrentHistogram getHistogram() { return ch; }
public void stop()
{
quit.set(true);
e.submit(new Callable<Void>()
{
@Override
public Void call() throws Exception
{
Thread.sleep(250);
ss.close();
return null;
}
});
}
@Override
public Void call() throws Exception
{
ss = new ServerSocket(port);
while (!quit.get() && !ss.isClosed())
{
try
{
e.submit(new ClientHandler(client.getAndIncrement(), ss.accept(), this));
}
catch (SocketException se)
{ continue; }
}
e.shutdown();
System.out.println(ch.toString());
while (!e.isTerminated()) { /* wait */ }
return null;
}
}
class ConcurrentHistogram
{
private final ConcurrentMap<Character, AtomicInteger> histogram = new ConcurrentHashMap<Character, AtomicInteger>();
private static final String HISTOGRAM_CHAR = "*";
public ConcurrentMap<Character, AtomicInteger> getHistogram() { return histogram; }
private String createAsterisk(int number)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < number; i++)
sb.append(HISTOGRAM_CHAR);
return sb.toString();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
List<Entry<Character, AtomicInteger>> data = new ArrayList<Entry<Character, AtomicInteger>>(histogram.entrySet());
Collections.sort(data, new Comparator<Entry<Character, AtomicInteger>>()
{
@Override
public int compare(Entry<Character, AtomicInteger> o1, Entry<Character, AtomicInteger> o2)
{
return o1.getKey().compareTo(o2.getKey());
}
});
for (Entry<Character, AtomicInteger> entry : data)
{
int value = entry.getValue().get();
sb.append(entry.getKey() + " " + String.format("%4s", "(" + value + ")") + " " + createAsterisk(value) + "\n");
}
return sb.toString();
}
public void addChar(Character c)
{
AtomicInteger value = histogram.get(c);
if (value == null)
{
histogram.putIfAbsent(c, new AtomicInteger());
value = histogram.get(c);
}
value.incrementAndGet();
}
}
class ClientHandler implements Callable<Void>
{
@SuppressWarnings ("unused")
private final int client;
private final Socket s;
private final Server server;
public ClientHandler(int client, Socket s, Server server)
{
this.client = client;
this.s = s;
this.server = server;
}
@Override
public Void call() throws Exception
{
DataInputStream in = new DataInputStream(s.getInputStream());
int c;
int i = 0;
byte[] bytes = new byte[2];
while ((c = in.read()) != -1)
{
if (i < 2)
{ bytes[i++] = ((byte) c); }
else if (Arrays.equals(bytes, DistributedHistogram.DATA))
{
i = 0;
char ch = (char) (((c & 0x00FF) << 8) + (in.read() & 0x00FF));
server.getHistogram().addChar(ch);
}
else if (Arrays.equals(bytes, DistributedHistogram.STOP))
{
i = 0;
server.stop();
}
else
{ i = 0; }
}
in.close();
s.close();
return null;
}
}
Hahah. Ce serait une bonne approche si comptant les occurrences de caractères dans la Bible.
: D pris mon temps, pour obtenir le serveur de quitter après i> le dernier message est envoyé. En attente avec f.get () code> seul, n'a pas aidé, j'ai dû ajouter un délai avant de fermer la prise de serveur ... BTW J'ai ajouté une troisième et dernière solution. C'est aussi court que possible. Au moins je le pense.
ici, une dernière réponse minimaliste
J'étais un peu inquiet de ne pas fermer le scanner. Mais puisque le javadoc dit system.in code>
est déjà ouvert et prêt à fournir des données d'entrée code>. Je suppose que la fermeture de la ressource est également traitée par le système. public class MinimalisticHistogram
{
public static void main(String[] args)
{
int[] occurrences = new int[(int) Math.pow(2, 16)]; // 256 KB
for (char c : new Scanner(System.in).nextLine().toCharArray()) occurrences[c]++;
for (int i = 0; i < occurrences.length; i++) if (occurrences[i] != 0) System.out.println(String.format("%c %4s %s", i, "(" + occurrences[i] + ")", new String(new char[occurrences[i]]).replace('\0', '*')));
}
}
Vous avez triché en cordant un tas d'énoncés sur cette ligne finale;)
Alors j'ai utilisé un double pour boucle le comptage des personnages. Si un caractère a été adapté à l'un des matrices, le nombre a été ajouté dans le troisième tableau.
for (int i = 0; i < zinArray.length; i++) {
char c = zinArray[i];
for (int j = 0; j < controleArray.length; j++) {
char d = controleArray[j];
if (c == d) {
letterCount[j]++;
break;
}
}
}
Voici comment j'ai fait l'algorithme avec Stressbuffer
A appeared 3 times B appeared 3 times C appeared 3 times 1 appeared 1 times 2 appeared 1 times 3 appeared 1 times
Utilisez un HASHMAP, en utilisant les caractères comme touches de la carte. Ensuite, c'est une simple question de (en pseudo-code)
carte [caractère] ++ code>.Oh, tu veux le nombre de seventions de chaque personnage. Duh. Savait que cela semblait trop facile. Pas que ce n'est pas facile. Marc B a la bonne idée.
Vous pouvez utiliser une carte code> ou même un tableau, car vous savez combien de caractères + numéros sont dans l'alphabet.
Est-ce que case importe? Ou devrait-il être traité le même?
var charcant = 0 var c = null; pour (var i = 0; i
Je suggère d'utiliser un tableau de
int [] code> plutôt que d'engendrer la surcharge d'unhashmap code>. Il serait intéressant de voir la performance de mon exemple par rapport à un exemplehashmap code>.