Java: le moyen le plus simple de remplacer des chaînes par des chaînes aléatoires

StackOverflow https://stackoverflow.com/questions/237058

  •  04-07-2019
  •  | 
  •  

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?

Était-ce utile?

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. *

  1. Oui, cela peut être fait avec des regex. Probablement pas très joliment, pas sans boucle ou deux
  2. Oui, cela peut être implémenté en Java.
  3. Voir au hasard , le package regex
  4. L'implémentation est laissée comme un exercice pour l'étudiant.

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top