Java: Easiest way to replace strings with random strings

By : Dove
Source: Stackoverflow.com
Question!

A string will be made up of certain symbols (ax,bx,dx,c,acc for example) and numbers.

ex: ax 5 5 dx 3 acc c ax bx

I want to replace one or all of the symbols (randomly) with another symbol of the same set. ie, replace one of {ax,bx,dx,c,acc} with one of {ax,bx,dx,c,acc}.

replacement example: acc 5 5 dx 3 acc c ax bx or c 5 5 dx 3 acc c ax ax

Is there a way to do this with regexes? In Java? If so, which methods should I use?

By : Dove


Answers

Use the Random class to generate a random int to choose the index of the symbols.

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

Make as many replacements as you need before you join the tokens back together.

There are two parts here that might seem tricky. First, the try catch to identify those tokens that are not integers. I recommend you pull that part out into its own method, since it works, but it's a bit hacky.

The second is where I set the source and target variables. What I'm doing there is getting a randomly selected index of one of the non-numeric symbols. Once I have two random indexes, I can swap them in the next line.

An alternative would be, to build up a new String from randomly selected symbols after you've split the original String into an array.



thanks a bunch guys. here's what i came up with. see if you can come up with a more efficient way.

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;
}
By : Dove


I think this is the most clean solution for replacing a certain set of symbols from a string containing a superset of them. appendreplacement is the key to this method. one important caveat: do not include any unescped dollar characters ($) in your elements list. escape them by using "\$" eventually use
.replaceall("\$","\\$"); on every string before adding it to the list. see also the javadoc in doubt about the $ signs.

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


This video can help you solving your question :)
By: admin