Java 将缩写/俚语替换为其完整形式

Java 将缩写/俚语替换为其完整形式,java,string,hashmap,Java,String,Hashmap,我使用HashMap存储缩写的完整表单 public class Test { public static void main(String[] args) { Map<String, String> slangs = new HashMap<String, String>(); slangs.put("lol", "laugh out loud"); slangs.put("r", " are ");

我使用HashMap存储缩写的完整表单

public class Test {
    public static void main(String[] args) {
        Map<String, String> slangs = new HashMap<String, String>();
        slangs.put("lol", "laugh out loud");
        slangs.put("r", " are ");
        slangs.put("n", " and ");
        slangs.put("idk", " I don't know ");
        slangs.put("u", " you ");
        Set set = slangs.entrySet();
        Iterator i = set.iterator();

        String sentence = "lol how are you";
        StringBuilder sb = new StringBuilder();

        for (String word : sentence.split(" ")) {
            while(i.hasNext()) {
                Map.Entry<String, String> me = (Map.Entry)i.next();
                if (word.equalsIgnoreCase(me.getKey())) {
                    sb.append(me.getValue());
                    continue;
                }
                sb.append(word);
            }
        }
        System.out.println(sb.toString());
    }
}

这里有什么问题,我该如何解决?

您不应该迭代条目以找到匹配项,您应该使用或获取给定缩写的完整形式,否则,您将使用
O(n)而不是时间复杂度为
O(1)
的完整形式来获取它
当然,这在性能方面并不好,但您将失去在
映射中拥有键/值对的真正好处。如果您是因为大小写而这样做的,只需将键放在地图中的小写字母中,然后调用
get
getOrDefault
,使用小写字母如下:

所以你的循环应该是这样的:

for (String word : sentence.split(" ")) {
    // Get the full form of the value of word in lower case otherwise use
    // the word itself
    sb.append(slangs.getOrDefault(word.toLowerCase(), String.format(" %s", word)));
}
输出:

laugh out loud how are you

使用,它可以是:

String result = Pattern.compile(" ")
    .splitAsStream(sentence)
    .map(word -> slangs.getOrDefault(word.toLowerCase(), word))
    .collect(Collectors.joining(" "));

简单地说,我认为您只需要检查
俚语
是否包含此关键字。 请检查我的密码

 public class Test {
    public static void main(String[] args) {

      Map<String, String> slangs = new HashMap<String, String>();
      slangs.put("lol", "laugh out loud");
      slangs.put("r", " are ");
      slangs.put("n", " and ");
      slangs.put("idk", " I don't know ");
      slangs.put("u", " you ");

      String sentence = "lol how are you";
      String[] words = sentence.split(" ");

      for (String word : words) {
        String normalizeWord = word.trim().toLowerCase();
        if(slangs.containsKey(normalizeWord)) {
            sentence = sentence.replace(word, slangs.get(normalizeWord));
        }
    }
    System.out.println(sentence);
  }
}
公共类测试{
公共静态void main(字符串[]args){
Map slags=newhashmap();
俚语。放(“lol”,“大声笑”);
俚语。put(“r”,“are”);
俚语。把(“n”,“and”);
俚语;
俚语。把(“u”、“你”);
String-sense=“lol你好吗”;
字符串[]单词=句子。拆分(“”);
for(字符串字:字){
字符串normalizeWord=word.trim().toLowerCase();
if(俚语containsKey(normalizeWord)){
句子=句子.替换(单词,俚语.get(normalizeWord));
}
}
System.out.println(句子);
}
}

不要在字典中的键上循环。相反,只需检查键是否在映射中并获得相应的值。另外,别忘了在组合句中加上空格

for (String word : sentence.split(" ")) {
    if (slangs.containsKey(word.toLowerCase())) {
        sb.append(slangs.get(word.toLowerCase()));
    } else {
        sb.append(word);
    }
    sb.append(" ");
}
如果您使用的是Java 8,还可以使用
String.join
Map.getOrDefault
和Streams:

String s = String.join(" ", Stream.of(sentence.split(" "))
        .map(word -> slangs.getOrDefault(word.toLowerCase(), word))
        .toArray(n -> new String[n]));

后一种方法还有一个好处,就是在句子的第一个单词之前或最后一个单词之后不加空格。

Idk为什么要把它弄得很复杂。我的第一个想法是,把句子分成几个单词,然后检查
俚语
是否包含它。你想要得到什么结果?输出应该是:“大笑,你好吗”@Mahn,但我该怎么做?试着打印所有结果,我不确定你为什么要使用它,而(i.hasNext())首先,你的句子不起作用,因为你是逐字逐句的,这意味着,例如在lol的情况下,你的句子中有俚语,而不是短语本身。我认为您应该检查internet上的一些解决方案,并以此为基础。
containsKey()
是多余的,如果您要调用
get()
。和
replaceAll()
可能会在正则表达式特殊字符上失败。如果要使用
replaceAll()
@shmosel,那么迭代单词而不是条目似乎有点倒退-我发现containsKey+的用法比直接访问var、测试var是否为null、然后使用更容易阅读。是的,效率稍低,但不应明显。我同意迭代顺序;这是一个更加明显的问题inefficiency@shmosel谢谢你的评论。我们同意,因为要遍历句子,所以应该使用
replace
。将更新我的答案。我认为如果不使用
containsKey()
,我们需要使用一些临时变量,如StringBuilder来获得正确答案。您应该使用
word.toLowerCase()
进行查找。另外,您可以使用
String[]::new
而不是
n->new String[n]
@shmosel,这两点都是一致的。奇怪的是,
String[]::new
在Eclipse中给了我奇怪的编译问题,所以无法测试,只更改了第一个。
for (String word : sentence.split(" ")) {
    if (slangs.containsKey(word.toLowerCase())) {
        sb.append(slangs.get(word.toLowerCase()));
    } else {
        sb.append(word);
    }
    sb.append(" ");
}