2

文字列は、特定の記号 (ax、bx、dx、c、acc など) と数字で構成されます。

例: ax 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

正規表現でこれを行う方法はありますか? ジャワで?その場合、どの方法を使用すればよいですか?

4

5 に答える 5

2

これは、特定の記号セットをそれらのスーパーセットを含む文字列から置き換えるための最もクリーンなソリューションだと思います。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();
}
于 2008-10-25T23:19:43.947 に答える
1

最初の質問に答えるには: いいえ。

ランダムな置換を行っているため、正規表現は役に立ちません。正規表現についてはランダムではありません。* 文字列は配列内にあるため、パターン マッチングで検索する必要がないため、正規表現は必要ありません。

**編集: 質問が編集されたため、文字列が配列内にあるとは言いません。この場合、それらがすべて 1 つの大きな文字列にあると仮定すると、他の回答に示されているように、置換する部分を見つけるために正規表現を作成できます。*

于 2008-10-25T22:02:52.480 に答える
0

Randomクラスを使用してランダムな int を生成し、シンボルのインデックスを選択します。

    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 キャッチ。機能するので、その部分を独自のメソッドに引き出すことをお勧めしますが、少しハッキーです。

source2 つ目は変数と変数を設定する場所targetです。私がそこで行っているのは、非数値記号の 1 つのランダムに選択されたインデックスを取得することです。2 つのランダム インデックスを取得したら、次の行でそれらを交換できます。

別の方法は、元の文字列を配列に分割した後、ランダムに選択されたシンボルから新しい文字列を作成することです。

于 2008-10-25T22:10:02.123 に答える
0
  1. はい、これは正規表現で行うことができます。おそらく、ループが 1 つまたは 2 つないわけではありません。
  2. はい、これは Java で実装できます。
  3. Random正規表現パッケージを参照してください
  4. 実装は、学生の演習として残されています。
于 2008-10-25T22:15:17.183 に答える
-1

たくさんの人に感謝します。これが私が思いついたものです。より効率的な方法を思いつくことができるかどうかを確認してください。

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;
}
于 2008-10-26T01:42:08.777 に答える