Java:文字列をランダムな文字列で置き換える最も簡単な方法
質問
文字列は、特定の記号(ax、bx、dx、c、accなど)と数字で構成されます。
例: x 5 5 dx 3 acc c ax bx
1つまたはすべてのシンボルを(ランダムに)同じセットの別のシンボルに置き換えたい。つまり、{ax、bx、dx、c、acc}のいずれかを{ax、bx、dx、c、acc}のいずれかに置き換えます。
交換の例: acc 5 5 dx 3 acc c ax bx または c 5 5 dx 3 acc c ax ax
正規表現でこれを行う方法はありますか? Javaで?その場合、どのメソッドを使用する必要がありますか?
解決
これは、スーパーセットを含む文字列から特定のシンボルセットを置き換えるための最もクリーンなソリューションだと思います。
appendreplacementは、このメソッドのキーです。
重要な注意点の1つは、要素リストに隠されていないドル記号($)を含めないことです。 " \ $"を使用してエスケープします
最終的に使用する
.replaceall(" \ $"、" \\ $");
リストに追加する前に、すべての文字列で。
javadoc の$記号に疑問がある。
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ReplaceTokens {
public static void main(String[] args) {
List<String> elements = Arrays.asList("ax", "bx", "dx", "c", "acc");
final String patternStr = join(elements, "|"); //build string "ax|bx|dx|c|acc"
Pattern p = Pattern.compile(patternStr);
Matcher m = p.matcher("ax 5 5 dx 3 acc c ax bx");
StringBuffer sb = new StringBuffer();
Random rand = new Random();
while (m.find()){
String randomSymbol = elements.get(rand.nextInt(elements.size()));
m.appendReplacement(sb,randomSymbol);
}
m.appendTail(sb);
System.out.println(sb);
}
/**
* this method is only needed to generate the string ax|bx|dx|c|acc in a clean way....
* @see org.apache.commons.lang.StringUtils.join for a more common alternative...
*/
public static String join(List<String> s, String delimiter) {
if (s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuffer buffer = new StringBuffer(iter.next());
while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
return buffer.toString();
}
他のヒント
最初の質問に答えるには:いいえ。
ランダム置換を行っているため、正規表現は役に立ちません。正規表現についてはランダムではありません。 *文字列は配列内にあるため、パターンマッチングで文字列を検索する必要はありません。そのため、正規表現は不要です。
**編集:質問が編集されたため、文字列が配列内にないことがわかります。この場合、それらがすべて1つの大きな文字列であると仮定すると、正規表現を作成して、他の回答に示すように、交換する部分を見つけることができます。*
ランダムを使用するランダムな整数を生成して、シンボルのインデックスを選択するクラス。
String text = "ax 5 5 dx 3 acc c ax bx";
System.out.println("Original: " + text);
String[] tokens = text.split(" ");
List<Integer> symbols = new ArrayList<Integer>();
for(int i=0; i<tokens.length; i++) {
try {
Integer.parseInt(tokens[i]);
} catch (Exception e) {
symbols.add(i);
}
}
Random rand = new Random();
// this is the part you can do multiple times
int source = symbols.get((rand.nextInt(symbols.size())));
int target = symbols.get((rand.nextInt(symbols.size())));
tokens[target] = tokens[source];
String result = tokens[0];
for(int i=1; i<tokens.length; i++) {
result = result + " " + tokens[i];
}
System.out.println("Result: " + result);
必要な数だけ 必要なだけ置換を行いますトークンを結合して一緒に戻します。
ここには、注意が必要な2つの部分があります。まず、整数ではないトークンを識別するためのtry catch。動作するので、その部分を独自のメソッドに引き出すことをお勧めしますが、少しハックです。
2番目は、 source
および target
変数を設定する場所です。そこで行っているのは、数字以外の記号の1つからランダムに選択されたインデックスを取得することです。 2つのランダムインデックスを取得したら、次の行でそれらを交換できます。
別の方法としては、元の文字列を配列に分割した後に、ランダムに選択されたシンボルから新しい文字列を構築することです。
たくさんの人に感謝します。ここに私が思いついたものがあります。より効率的な方法を考え出すことができるかどうかを確認してください。
private final String[] symbolsPossible = {"ax","bx","cx","dx","foo"};
private boolean exists;
private final String mutate(String s)
{
String[] tokens=s.split(" ");
for(int j=0; j<tokens.length; j++)
if(Math.random()<.1) //10% chance of mutation per token
{
//checking to see if the token is a supported symbol
exists=false;
for(int i=0; i<symbolsPossible.length; i++)
if(tokens[j].equals(symbolsPossible[i]))
exists=true;
if(exists)
tokens[j]=symbolsPossible[(int)Math.random()*symbolsPossible.length];
}
StringBuffer result=new StringBuffer();
for(String t:tokens)
result.append(t);
return result;
}