Je travaille actuellement sur un projet pour compter la fréquence des mots dans un fichier texte. Le programme pilote place les mots dans un ArrayList (après les avoir mis en minuscules et en supprimant les espaces), puis l'objet FreqCount place le ArrayList dans un HashMap qui gérera les opérations de fréquence. Jusqu'à présent, je peux demander au pilote de lire le fichier texte, de le mettre dans une ArrayList, puis de le placer dans le HashMap. Mon problème est que les nœuds HashMap ne se répètent pas, donc j'essaie d'incrémenter la valeur chaque fois que le mot est vu.
Chauffeur:
one, one, one, one one one one one one one one one one one one one one eleven ten nine eight seven six five four three two one Hashmap: key: nine value: 1 key: one, value: 1 key: six value: 1 key: four value: 1 key: one value: 1 key: seven value: 1 key: eleven value: 1 key: ten value: 1 key: five value: 1 key: three value: 1 key: two value: 1 key: eight value: 1
FreqCount:
ONE TWO ThReE FoUR fIve six seven EIGHT NINE TEN ELEVEN ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE ONE, ONE, ONE,
Fichier texte:
package threetenProg3; import java.util.HashMap; import java.util.List; public class FreqCount { //attributes and initializations private HashMap<String, Integer> map = new HashMap<String, Integer>(); //constructors FreqCount(List<String> driverList){ for(int dLIndex = driverList.size()-1; dLIndex>=0; dLIndex--) { //puts list into hashmap for(String mapKey : map.keySet()) { if(mapKey.equals(driverList.get(dLIndex))) { int tval = map.get(mapKey); map.remove(mapKey); map.put(mapKey, tval+1); }else { map.put(mapKey, 1); } } } } //methods public void printMap() { for (String i : map.keySet()) { //function ripped straight outta w3schools lol System.out.println("key: " + i + " value: " + map.get(i)); } } //*/ }
Production:
package threetenProg3; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; import java.util.ArrayList; public class Driver { public static void main(String[] args) throws FileNotFoundException{ File in = new File("test.txt"); Scanner scanFile = new Scanner(in); ArrayList<String> parsed = new ArrayList<String>(); while(scanFile.hasNext()) { //if this ends up cutting off bottom line, make it a do while loop parsed.add(scanFile.next().toLowerCase()); } for(int i = parsed.size()-1; i>=0; i--) { //prints arraylist backwards System.out.println(parsed.get(i)); } //*/ FreqCount fc = new FreqCount(parsed); System.out.println("\n Hashmap: \n"); fc.printMap(); scanFile.close(); } }
D'après ce que je vois, la sortie devrait imprimer les valeurs correctes pour les fréquences des touches. Merci d'avance pour votre aide!
3 Réponses :
Vous pouvez modifier la définition de FreqCount
comme suit:
FreqCount(List<String> driverList) { for (int dLIndex = driverList.size() - 1; dLIndex >= 0; dLIndex--) { String key = driverList.get(dLIndex); map.put(key, map.getOrDefault(key, 0) + 1); } }
Sortie après ce changement:
Hashmap: key: nine value: 1 key: one, value: 3 key: six value: 1 key: four value: 1 key: one value: 15 key: seven value: 1 key: eleven value: 1 key: ten value: 1 key: five value: 1 key: three value: 1 key: two value: 1 key: eight value: 1
Alternativement,
FreqCount(List<String> driverList) { for (int dLIndex = driverList.size() - 1; dLIndex >= 0; dLIndex--) { String key = driverList.get(dLIndex); if (map.get(key) == null) { map.put(key, 1); } else { map.put(key, map.get(key) + 1); } } }
Map#getOrDefault
renvoie la valeur à laquelle la clé spécifiée est mappée, ou la valeur par défaut si cette carte ne contient aucun mappage pour la clé.
Cela ressemble exactement à ce dont j'ai besoin, mais après avoir retaper le code dans mon éclipse, il imprime toujours toutes les valeurs comme 1. Même copier-coller directement à partir d'ici dans le code produit les mêmes résultats. Pour être clair, cela s'est produit pour tous ces correctifs, pas seulement pour les vôtres.
Ça ne fait rien! J'ai supposé que c'était un problème d'éclipse et j'ai tout déplacé vers un nouveau projet. Ça fonctionne maintenant. Merci beaucoup!!
Vous avez plusieurs problèmes là-bas.
one one one one one one one one one one one one one one one one one eleven ten nine eight seven six five four three two one Hashmap: key: nine value: 1 key: six value: 1 key: four value: 1 key: one value: 18 key: seven value: 1 key: eleven value: 1 key: ten value: 1 key: five value: 1 key: three value: 1 key: two value: 1 key: eight value: 1
Vous faites une boucle for bizarre là-bas en essayant de parcourir une carte vide. Vous devez vérifier s'il y a une clé pour ce mot dans la carte, s'il y en a, vous en ajoutez une à la valeur et s'il n'y en a pas, vous ajoutez la nouvelle paire avec la valeur 1.
Et pour éviter le nombre avec des virgules ou des points (si vous le souhaitez, vous pouvez ajouter d'autres caractères à l'expression régulière que replaceAll prend comme paramètre)
while(scanFile.hasNext()) { //if this ends up cutting off bottom line, make it a do while loop String value = scanFile.next().toLowerCase(); value = value.replaceAll("[,.]", ""); parsed.add(value); }
La sortie est maintenant
FreqCount(List<String> driverList){ for(int dLIndex = driverList.size()-1; dLIndex>=0; dLIndex--) { //puts list into hashmap if(map.get(driverList.get(dLIndex)) != null) { int tval = map.get(driverList.get(dLIndex)); map.remove(driverList.get(dLIndex)); map.put(driverList.get(dLIndex), tval+1); }else { map.put(driverList.get(dLIndex), 1); } } }
sans répétitions sur les mots même avec des virgules et le décompte correct de chacun
Merci! Je ne pense pas que nous ayons encore couvert les regex, je vais donc l'examiner plus en profondeur pour voir si c'est quelque chose que mon professeur veut ici.
Le moyen le plus simple de le faire, imo, est d'utiliser la méthode Map.merge . La méthode prend la valeur précédente et applique une fonction de mappage. Dans ce cas, la deuxième valeur n'est pas utilisée. La première valeur est utilisée pour remplacer la valeur existante + 1. Ainsi, vous obtenez la fréquence d'occurrence des chaînes.
Notez également que j'ai changé notre classe pour utiliser une méthode d' parse
qui renvoie la carte. Il n'est pas approprié de faire beaucoup de calculs dans un constructeur de classe.
Après avoir lu les valeurs.
class FreqCount { // attributes and initializations private Map<String, Integer> map = new HashMap<>(); public Map<String, Integer> parse (List<String> driverList) { for (String str : driverList) { map.merge(str, 1, (v1,notUsed)->v1 + 1); } return map; } }
impressions
nine=1 one,=3 six=1 four=1 one=15 seven=1 eleven=1 ten=1 five=1 three=1 two=1 eight=1
La classe modifiée
FreqCount fc = new FreqCount(); Map<String,Integer> map = fc.parse(parsed); map.entrySet().forEach(System.out::println);
Malheureusement, cela fait partie de la tâche que je ne peux pas utiliser ces fonctions de carte avancées (désolé aurais dû le mentionner). J'ai eu ma réponse mais merci beaucoup!