Java: le moyen le plus simple de remplacer des chaînes par des chaînes aléatoires
Question
Une chaîne sera composée de certains symboles (ax, bx, dx, c, acc par exemple) et de nombres.
ex: axe 5 5 dx 3 acc c ax bx
Je souhaite remplacer un ou tous les symboles (de manière aléatoire) par un autre symbole du même ensemble. c'est-à-dire, remplacez l'un de {ax, bx, dx, c, acc} par l'un des {ax, bx, dx, c, acc}.
exemple de remplacement: acc 5 5 dx 3 acc c ax bx ou c 5 5 dx 3 acc c ax ax
Existe-t-il un moyen de faire cela avec les regex? En Java? Si oui, quelles méthodes devrais-je utiliser?
La solution
Je pense que c'est la solution la plus propre pour remplacer un certain ensemble de symboles d'une chaîne contenant un sur-ensemble d'entre eux.
appendreplacement est la clé de cette méthode.
Une mise en garde importante: n'incluez aucun caractère dollar non échappé ($) dans votre liste d'éléments. échapper à eux en utilisant " \ $ "
éventuellement utiliser
.replaceall ("\ $", "\\ $");
sur chaque chaîne avant de l'ajouter à la liste.
voir aussi le javadoc dans le doute sur les signes $.
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();
}
Autres conseils
Pour répondre à la première question: non.
Puisque vous effectuez un remplacement aléatoire, regex ne vous aidera pas, rien n’est aléatoire. * Puisque vos chaînes sont dans un tableau, vous n'avez pas besoin de les trouver avec une correspondance de motif, donc encore une regex n'est pas nécessaire.
** Modifier: la question a été modifiée de sorte que les chaînes ne figurent plus dans un tableau. Dans ce cas, en supposant qu'ils soient tous dans une grande chaîne, vous pouvez créer une expression rationnelle pour rechercher les parties que vous souhaitez remplacer, comme indiqué dans les autres réponses. *
Utilisez le au hasard . classe pour générer un int aléatoire pour choisir l’index des symboles.
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);
Effectuez autant de remplacements que nécessaire avant joindre les jetons ensemble.
Il y a deux parties ici qui peuvent sembler délicates. Tout d’abord, essayez d’identifier les jetons qui ne sont pas des entiers. Je vous recommande de tirer cette partie dans sa propre méthode, car cela fonctionne, mais c'est un peu hacky.
La deuxième étape consiste à définir les variables source
et cible
. Ce que je fais ici consiste à obtenir un index sélectionné au hasard parmi l'un des symboles non numériques. Une fois que j'ai deux index aléatoires, je peux les échanger à la ligne suivante.
Une autre solution serait de créer une nouvelle chaîne à partir de symboles sélectionnés de manière aléatoire après avoir divisé la chaîne d'origine en un tableau.
merci beaucoup les gars. voici ce que je suis venu avec. voyez si vous pouvez trouver un moyen plus efficace.
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;
}