1

画像に置き換える必要がある特定のマーカーを含む一連の文字列があります。最初に、マーカーと画像を使用してハッシュ マップを作成しました。

Map<String, String> images = new HashMap<String, String>();
images.put(":img:howdy:", "path/images/hello.png");
images.put(":img:code:", "path/images/code.png");
images.put(":img:smile:", "path/images/sm.png");
//...and 70 more records

文字列は次のようになります。

これは文字列です :img:howdy: ですね :img:smile:

さらに:img:smile:

これは images:img:code::img:smile の文字列です:

解析後、すべてのマーカーは画像に置き換えられる予定です。

私は次の点で立ち往生しました:

Map<String, String> images = new HashMap<String, String>();
images.put(":img:howdy:", "path/images/hello.png");
images.put(":img:code:", "path/images/code.png");
images.put(":img:smile:", "path/images/sm.png");

String[] strings = {"This is a string :img:howdy:, you know it :img:smile:",
                 "And even more:img:smile:",
                 "This is a string with images:img:code::img:smile:"};

for (String text : images.keySet()) {
    for (String string : strings) {
        if(string.contains(text)) {
            string.replace(text, images.get(text));
        }
    }
}

まず、マーカーが置き換えられますが、反復が多すぎます。第 2 に、たとえば StringBuilder を使用すると、いくつかのマーカーが置き換えられ、いくつかのマーカーが置き換えられずに多くの重複が発生します。

私は文字列の解析とそれに対応するアルゴリズムに (現時点では) 強くないので、選択したアプローチを見た後で石を投げつけないでください。

Dariusz Waver が提案したように少し作り直して追加しまし た。ここに私が持っているものがあります:

private final String IMAGE_PATTERN = ":s:\\w+:";

//.......

Pattern p = Pattern.compile(IMAGE_PATTERN);
Matcher m = p.matcher(message);
while(m.find())
{
    String imgPattern = message.substring(m.start(), m.end());
    String imgPath = ImgPaths.images.get(imgPattern);
    
    //If there's no such image in Images Map
    if(imgPattern != null) {
        message = message.replace(imgPattern, imgPath);
        m.reset(message);
    }
}

StringBuilder result = new StringBuilder();
result.append(timestamp).append(" - ").append(sender)
        .append(": ").append(message);

非常に膨大な量のテキストがあることを考慮して、より最適化する方法はありますか?

4

4 に答える 4

1

StringTemplateのようなテンプレートライブラリを試してみませんか?

サンプルコード:

String[] strings = {"This is a string <howdy>, you know it <smile>",
                     "And even more <smile>",
                     "This is a string with images <code><smile>"};

for (String string : strings) {
    ST hello = new ST(string);

    hello.add("howdy", "path/images/hello.png");
    hello.add("code", "path/images/code.png");
    hello.add("smile", "path/images/sm.png");

    System.out.println(hello.render());
}

Why do you want to reinvent the wheel?

于 2013-02-18T10:44:32.423 に答える
1

逆の方法をお勧めします。最初に regex の出現箇所をすべて見つけて:\w+:\w+から、マップ内でその値を検索し、見つかった場合は文字列を置き換えます。

大量の画像と大量のテキストの場合は、より良い方法です。

ただし、コードは非常にきれいで、パフォーマンスの問題がない場合は、そのままにしておくことができます - jlordo によって投稿された修正を実際に行っている場合:

for (int i = 0; i < strings.length; i++) {
    if(strings[i].contains(text)) {
        strings[i] = strings[i].replace(text, images.get(text));
    }
}
于 2013-02-18T10:16:02.983 に答える
1

string内側の for ループのローカル変数です。string.replace()新しい文字列を作成し、現在の文字列を変更しません。ただし、再割り当てしても配列の内容は変更されないため、ここでもstring = string.replace(...)役に立ちません。

内部の for ループを次のように置き換える必要があります。

for (int i = 0; i < strings.length; i++) {
    if(strings[i].contains(text)) { // this check is not really necessary
        strings[i] = strings[i].replace(text, images.get(text));
    }
}
于 2013-02-18T10:15:27.047 に答える
0

1-.contains必要ないようです

2-あなたがしなければならない文字列は不変ですString string = string.replaceAll(...)

于 2013-02-18T10:17:23.477 に答える