HashMap以小数形式打印字母频率?



我有这样的代码:

public String LetterFreq(String t) {
HashMap<Character,Double> map= new HashMap<Character, Double>();
for(int i=0;i< t.length();i++) {
char c=  t.charAt(i);
Double val = map.get(c);
if(val!= null) {
map.put(c,new Double(val +1));
}
else {
map.put(c, 1.0);
}


}
for (Entry<Character, Double> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + (entry.getValue()/t.length()));
}

在这段代码中,它遍历我给出的字符串的每个字母,如果有多个字母,则将一个计数映射到键。此外,在打印该行时,它将数字(计数)除以整个字符串的长度。我遇到的问题是,当我在里面输入文本时,我希望输出看起来像这样:

letter: decimalvalue
letter: decimalvalue

但是我得到了这个

: decimal value
letter: decimavalue
letter:decimalvalue...

一些变化,无论我有一个没有字母的空格,它给出了一个十进制值,我不明白为什么?

更新:

我假设这与字符串中的空格有关,但是当我像thisisjulz一样一起输入文本时,我们可以在这里看到字母s出现2/10,这应该意味着。2,但相反,我的代码在我没有像上面引用的例子中看到的那样在偶数中注册空格,并将其计数为1个字符空间。有没有什么方法可以实现分隔符或其他东西来确保它只计算有值的字符?

Updatev2:这是我抓取"string "这一切是如何结合在一起的:alice将i输入到控制台的值发送给eve, eve函数所做的就是LetterFreq(tex);

public void Alice() 
{
System.out.println("Would you like to encrpyt a message or quit?");
System.out.println("To Encrypt press enter 9.");
System.out.println("If you wish to quit enter 0.");
System.out.println("If you made a mistake and want to go back to the main menu press 7.");
Scanner q = new Scanner(System.in);

switch (q.nextInt()) 
{
case 0:
System.out.println ("Thank you and goodbye.");
break;
case 9:
System.out.println ("Please enter text:");


String tex ="";
String line;
while (in.hasNextLine()) {
line = in.nextLine();
if (line.isEmpty()) {
break;
}
tex += line + "n";
}

tex= Encryption(tex);
System.out.println(tex+"n");
System.out.println("Would you like to simulate Bob Or Eve? ");
System.out.println("Enter 5 for Bob, 6 For Eve");

in.hasNextInt();
if(in.nextInt()==5) {
tex= tex.replaceAll(" ", "");
Bob(tex); 
}
if (in.nextInt()==6) {
tex= tex.replaceAll(" ", "");
Eve(tex);
}
else {

break;
}
case 7:
new Menu();
default:
System.err.println ( "Unrecognized option" );
break;
}

下面是一个使用正则表达式replaceAll(…)的完整示例。此外,我更新了你的代码使用containsKey(c)而不是获取和检查获取的值是否为空。它更优雅一点。

package eu.webfarmr;
import java.util.HashMap;
import java.util.Map.Entry;
public class LetterFrequency {
public static void main(String[] args) {
letterFreq("Some Example 38 sdf %");
}
public static void letterFreq(String t) {
t = t.replaceAll("[^a-zA-Z]", "");
HashMap<Character, Double> map = new HashMap<Character, Double>();
for (int i = 0; i < t.length(); i++) {
char c = t.charAt(i);
if (map.containsKey(c)) {
Double d = map.get(c);
d++;
map.put(c, d);
} else {
map.put(c, 1.0);
}
}
for (Entry<Character, Double> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + (entry.getValue() / t.length()));
}
}
}

在Java 8中有一个简洁的map函数,你可以使用它来进一步压缩你的代码:map.merge(c, 1.0, Double::sum);。请参阅下面的代码片段。本质上,它所做的是设置1作为值,如果没有值,否则递增。

public static void letterFreq(String t) {
t = t.replaceAll("[^a-zA-Z]", "");
HashMap<Character, Double> map = new HashMap<Character, Double>();
for (int i = 0; i < t.length(); i++) {
char c = t.charAt(i);
map.merge(c, 1.0, Double::sum);
}
}

我无法重现你所看到的。我复制了你的代码并做了一个测试:

public String LetterFreq(String t) {
HashMap<Character, Double> map = new HashMap<Character, Double>();
for (int i = 0; i < t.length(); i++) {
char c = t.charAt(i);
Double val = map.get(c);
if (val != null) {
map.put(c, new Double(val + 1));
} else {
map.put(c, 1.0);
}

}
for (Map.Entry<Character, Double> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + (entry.getValue() / t.length()));
}
return t;
}
@Test public void testLetterFreq() {
LetterFreq("thisisjulz");
}

我生产:

s:0.2
t:0.1
u:0.1
h:0.1
i:0.2
j:0.1
z:0.1
l:0.1

…这对我来说似乎是正确的

最新更新