Java 如何获得地图中重复次数最多的5个元素?
我想写一个程序,例如显示文本中重复次数最多的5个单词。 保存在地图中的文字,其关键字为文字,其值为重复该文字的次数 这个程序显示重复次数最多的单词,但我不知道如何改进它以显示5个重复次数最多的单词(以及如何使用map代替list)Java 如何获得地图中重复次数最多的5个元素?,java,python-3.x,kotlin,Java,Python 3.x,Kotlin,我想写一个程序,例如显示文本中重复次数最多的5个单词。 保存在地图中的文字,其关键字为文字,其值为重复该文字的次数 这个程序显示重复次数最多的单词,但我不知道如何改进它以显示5个重复次数最多的单词(以及如何使用map代替list) 导入java.io.BufferedReader; 导入java.io.FileReader; 导入java.util.ArrayList; 公共类最重复的单词{ 公共静态void main(字符串[]args)引发异常{ 字符串行,word=“”; int coun
导入java.io.BufferedReader;
导入java.io.FileReader;
导入java.util.ArrayList;
公共类最重复的单词{
公共静态void main(字符串[]args)引发异常{
字符串行,word=“”;
int count=0,maxCount=0;
ArrayList words=新的ArrayList();
//以读取模式打开文件
FileReader文件=新的FileReader(“data.txt”);
BufferedReader br=新的BufferedReader(文件);
//读每一行
而((line=br.readLine())!=null){
字符串[]=line.toLowerCase().split(([,.\\s]+))”;
//将上一步中生成的所有单词添加到单词中
对于(字符串s:String){
字。加上(s);
}
}
//确定文件中重复次数最多的单词
对于(inti=0;i最大计数){
最大计数=计数;
单词=单词。获取(i);
}
}
System.out.println(“最重复的单词:“+word”);
br.close();
}
}
按如下方式尝试:
Map<String, Integer> words = new HashMap<>();
try (BufferedReader br = new BufferedReader(new FileReader("data.txt "))) {
String line;
while ((line = br.readLine()) != null) {
String string[] = line.toLowerCase().split("([,.\\s]+) ");
//Adding all words generated in previous step into words
for (String s : string) {
words.compute(s, (word, count) -> {
if (count == null)
return 1;
return count + 1;
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
final int TOP = 5;
final List<Integer> topCounts = words.values().stream()
.sorted(Comparator.reverseOrder())
.limit(TOP)
.collect(Collectors.toList());
final String[] topWords = new String[TOP];
words.forEach((word, count) -> {
int indexOfWord = topCounts.indexOf(count);
if (indexOfWord > -1) {
topWords[indexOfWord] = word;
topCounts.set(indexOfWord, -1);
}
});
System.out.println("Top 5 most repeated words: " + Arrays.toString(topWords));
Map words=newhashmap();
try(BufferedReader br=new BufferedReader(new FileReader(“data.txt”)){
弦线;
而((line=br.readLine())!=null){
字符串[]=line.toLowerCase().split(([,.\\s]+))”;
//将上一步中生成的所有单词添加到单词中
for(字符串s:String){
单词。计算(单词,计数)->{
如果(计数=null)
返回1;
返回计数+1;
});
}
}
}捕获(IOE异常){
e、 printStackTrace();
}
最终int TOP=5;
最终列表topCounts=words.values().stream()
.sorted(Comparator.reverseOrder())
.限制(顶部)
.collect(Collectors.toList());
最终字符串[]topWords=新字符串[TOP];
单词。forEach((单词,计数)->{
int indexoford=topCounts.indexOf(count);
如果(indexoford>-1){
topWords[indexOfWord]=单词;
topCounts.set(indexoford,-1);
}
});
System.out.println(“重复次数最多的前5个单词:“+Arrays.toString(topWords));
简单的方法是首先计算每个单词的频率(计算它出现的次数),然后按频率对单词进行排序,然后显示结果的前五名。实际上,您不需要对所有这些文件进行排序,但这比只选择前5名要简单
让我们编写一些代码:
class WordCounter {
private Map<String, Integer> counts = new HashMap<>();
public void count(String word) {
int prev = counts.getOrDefault(word, 0);
counts.put(word, prev+1);
}
public String[] top(int n) {
String[] sorted = new String[counts.size()];
int i=0;
for (String s : counts.keySet()) sorted[i++] = s;
Arrays.sort(sorted, (a,b) -> counts.get(b).compareTo(counts.get(a)));
return Arrays.copyOfRange(sorted, 0, n);
}
}
类字计数器{
私有映射计数=新HashMap();
公共无效计数(字符串字){
int prev=counts.getOrDefault(字,0);
计数。输入(字,上一个+1);
}
公共字符串[]顶部(整数n){
字符串[]排序=新字符串[counts.size()];
int i=0;
对于排序为[i++]=s的(字符串s:counts.keySet());
Arrays.sort(sorted,(a,b)->counts.get(b).compareTo(counts.get(a));
返回数组.copyOfRange(排序,0,n);
}
}
现在,我们在阅读每个单词后调用
count(word)
。这需要考虑频率。并在完成后调用top(5)
,这将按计数(递减)对结果进行排序并返回前5名。这是函数式风格可以导致代码更短的情况之一,希望更容易理解
一旦你有了单词列表
,你就可以简单地使用:
words.groupingBy{ it }
.eachCount()
.toList()
.sortedByDescending{ it.second }
.take(5)
groupingBy()
从单词列表中创建一个键。(通常,您会提供一个键选择器函数,解释如何对项目进行分组,但在这种情况下,我们需要单词本身,因此it
)因为我们只关心出现的次数,eachCount()
获取计数(感谢Ilya和Tenfour04的支持。)
然后我们将映射转换成一个列表,准备进行排序。该列表由成对组成,单词作为第一个值,计数作为第二个值
因此,sortedByDescending{it.second}
按计数排序。由于我们按降序排序,它首先给出最常用的单词
最后,take(5)
从列表中获取前五个值,这将是五个最常见的单词(以及它们的计数)
例如,当我在几个简单的句子上运行时,它给出:[(the,4),(was,3),(it,3),(a,2),(of,2)]
(如果您只需要单词,而不需要计数,那么可以使用.map{it.first}
。此外,正如Tenfour04所建议的,有更好的方法从文本中提取单词;但一旦你开始考虑大小写、撇号、连字符、非ASCII字母等,这可能会变得相当复杂。这似乎是一个与获取最常用单词不同的问题。)因为你标记了Kotlin,h
words.groupingBy{ it }
.eachCount()
.toList()
.sortedByDescending{ it.second }
.take(5)