Domanda

Una stringa sarà composta da alcuni simboli (ax, bx, dx, c, ad esempio) e numeri.

es: ascia 5 5 dx 3 acc c ax bx

Voglio sostituire uno o tutti i simboli (in modo casuale) con un altro simbolo dello stesso set. vale a dire, sostituire uno di {ax, bx, dx, c, acc} con uno di {ax, bx, dx, c, acc}.

esempio di sostituzione: acc 5 5 dx 3 acc c ax bx o c 5 5 dx 3 acc ascia c

C'è un modo per farlo con le regex? In Java? In tal caso, quali metodi dovrei usare?

È stato utile?

Soluzione

Penso che questa sia la soluzione più pulita per sostituire un certo set di simboli da una stringa che ne contiene un superset. appendreplacement è la chiave di questo metodo. un avvertimento importante: non includere alcun carattere di dollaro senza caratteri ($) nell'elenco degli elementi. sfuggirli usando " \ $ " eventualmente utilizzare
    .ReplaceAll (" \ $ ", " \\ $ "); su ogni stringa prima di aggiungerla all'elenco. vedi anche javadoc in dubbio sui segni $.

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

Altri suggerimenti

Per rispondere alla prima domanda: no.

Poiché stai effettuando una sostituzione casuale, regex non ti aiuterà, nulla di regex è casuale. * Dato che le tue stringhe sono in un array, non è necessario trovarle con alcun pattern matching, quindi nuovamente regex non è necessario.

** Modifica: la domanda è stata modificata, quindi non dice più che le stringhe sono in un array. In questo caso, supponendo che siano tutti in una grande stringa, potresti creare una regex per trovare le parti che desideri sostituire, come mostrato in altre risposte. *

  1. Sì, questo può essere fatto con regex. Probabilmente non molto graziosamente, no senza un ciclo o due
  2. Sì, questo può essere implementato in Java.
  3. Vedi Random , il regex pacchetto
  4. L'implementazione è lasciata come esercizio per lo studente.

Utilizza Random classe per generare un int casuale per scegliere l'indice dei simboli.

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

Apporta tutte le sostituzioni necessarie prima < join i token di nuovo insieme.

Ci sono due parti qui che potrebbero sembrare complicate. Per prima cosa, prova a catturare per identificare quei token che non sono numeri interi. Ti consiglio di estrarre quella parte nel suo metodo, dal momento che funziona, ma è un po 'confuso.

Il secondo è dove ho impostato le variabili source e target . Quello che sto facendo è ottenere un indice selezionato casualmente di uno dei simboli non numerici. Una volta che ho due indici casuali, posso scambiarli nella riga successiva.

Un'alternativa sarebbe quella di creare una nuova stringa da simboli selezionati casualmente dopo aver diviso la stringa originale in un array.

grazie mille ragazzi. ecco cosa mi è venuto in mente. vedere se riesci a trovare un modo più efficiente.

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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top