2017-01-16 5 views
2

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()); 
    } 
} 

出力は次のようになります。ここで間違っているとどのように私はそれを解決するのです

lollollollaugh out loudlol 

何?あなたはマッチを見つけるために、エントリを反復することになっていません

+0

Idkなぜあなたはそれをかなり複雑にしますか?私の最初の考えでは、文章を単語に分割し、「スラング」にそれが含まれているかどうかを確認してください。 –

+0

あなたはどのような結果を得たいですか? –

+0

出力は次のようにする必要があります。「あなたは大声で笑うよ」 –

答えて

5

、あなたは、そうでない場合は代わりにO(1)の時間複雑で、あなたの完全な形を得るための、与えられた略語の完全な形を得るためにget(Object key)またはgetOrDefault(Object key, V defaultValue)を使用することになっていますあなたはO(n)でそれを得るでしょうが、それはもちろんパフォーマンスの面では良くないです、あなたはMapのあなたのキーと値のペアを持つ本当の利点を失うでしょう。

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))); 
} 
:だからあなたのループのようなものでなければなりません

を:あなたが原因の場合のそれをしなかった場合は、単にあなたのマップにのみ小文字であなたの鍵を入れて、以下のように小文字で単語をgetまたはgetOrDefaultを呼び出します

出力:

laugh out loud how are you 

Stream APIを使用して、それは、SIM可能性プライ可能:

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

は単に、私はあなただけslangsこのキーワードが含まれているかいないかどうかを確認する必要があると思います。 私のコードを確認してください。

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); 
    } 
} 
+1

'get()'を呼び出す場合、 'containsKey()'は冗長です。 'replaceAll()'は正規表現の特殊文字で失敗することがあります。そして 'replaceAll()'を使うつもりならば、エントリの代わりに単語を反復するのは少し後ろにあるようです。 – shmosel

+0

@shmosel - 私は実際にcontainsKey +の使用が、まっすぐなget-to-var、nullをテストするvarより少し読みやすくなり、使用することがわかります。はい、少し効率が悪いですが、目立たないようにしてください。私は反復順序に同意します。それは*多くの*顕著な非効率性です – tucuxi

+0

@shmoselご意見ありがとうございます。文をループで実行するので、 'replace'を使うべきだと合意してください。私の答えが更新されます。私は 'containsKey()'を使わないと、正しい答えを得るためにStringBuilderのような一時変数を使う必要があると思います。 –

3

辞書のキーをループしないでください。代わりに、キーがマップにあるかどうかを確認し、対応する値を取得します。また、スペースを結合した文に戻すことを忘れないでください。あなたは、Java 8を使用している場合

for (String word : sentence.split(" ")) { 
    if (slangs.containsKey(word.toLowerCase())) { 
     sb.append(slangs.get(word.toLowerCase())); 
    } else { 
     sb.append(word); 
    } 
    sb.append(" "); 
} 

、あなたもString.joinMap.getOrDefaultとストリームを使用することができます。

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

は、この後者のアプローチはまた、最初の前または最後の後にスペースを追加しないという利点を持っています文中の単語。

+0

ルックアップには 'word.toLowerCase()'を使うべきです。また、 'n - > new String [n]'の代わりに 'String [] :: new'を使うこともできます。 – shmosel

+0

@shmosel両方の点で合意しました。不思議なことに、 'String [] :: new'はEclipseで奇妙なコンパイルの問題を抱えていましたが、テストできず、最初のものだけを変更しました。 –