5

I have a string:

String text = "Nothing right in my brain. Nothing left in my brain"

I want to create a new string text2 that has 2-4 random new line from previous, such as:

"Nothing \n right \n in my brain.  \n Nothing left in my brain"

or

"Nothing right in \n my brain. Nothing left in \n my brain"

How to create a new string with random new line between the words? I am thinking to get the index of whitespace, in order to insert new line after random whitespace. But I only keep getting the first whitespace index. Anyone know better approach to solve this? Thank you.

Tom
  • 14,120
  • 16
  • 41
  • 47
Lynx
  • 111
  • 8

6 Answers6

5

There are three stages to your problem, splitting the String, inserting randomness and using them together...

Splitting a String

Break it into words with String.split(), which creates an array of Strings (in this case words) by spaces.

  String[] words = text.split(" "); //Split by spaces

then rebuild your String with newlines added for instance:-

 StringBuiler sb = new StringBuilder();
 for (String word : words)
 {
   sb.append(word + "\n");
 }
 String text2 = sb.toString();

In this case you will insert a newline in between every word and save the result in text2.

Inserting Randomness

You could just create a Random object...

    Random random = new Random(); 

Then use it in the code that inserts your newline, like so...

//Randomly add or don't add a newline (Compacted with a ternary operator instead of an 'if')
sb.append(word + (random.nextBoolean() ? "\n" : ""));

Bringing it together (TLDR)

Then all you need to do is maintain a count of inserted newlines and limit them to that. So your code becomes:-

 int requiredNewlines = random.nextInt(2 - 5) + 2; //Number between 2-4
 for (String word : words) //For each word
 {
   sb.append(word); //Add it
   if (requiredNewlines >= 0 && random.nextBoolean()) 
   {
   //Randomly add newline if we haven't used too many
      sb.append("\n"); 
      requiredNewlines--;
   }
 }
 String text2 = sbAppen.toString();

Additionally

Although the randomness in this example fits your purpose here it is not the ideal implementation of random (as mentioned in the comments), in that there is more bias towards one appearing nearer the start of the String than the end and that there no chance of it appearing before the first word.

There is also another option of using StringTokenizer instead of String.split() which I much prefer but it doesn't deal with regex and is falling out of use, so I've changed my answer to use String.split()

Community
  • 1
  • 1
Ross Drew
  • 7,575
  • 2
  • 36
  • 51
  • 2
    I'm not the voter, but you shouldn't use the `StringTokenizer` class anymore. Use `String.split` instead. – Tom Jun 26 '15 at 11:55
  • 1
    @Tom AFAIK performance on `StringTokenizer` is better than `split` – xrisk Jun 26 '15 at 11:58
  • 1
    I always preferred Tokenizer but really you're right Tom. Changed. – Ross Drew Jun 26 '15 at 12:00
  • http://stackoverflow.com/questions/691184/scanner-vs-stringtokenizer-vs-string-split – xrisk Jun 26 '15 at 12:01
  • I also have a _feeling_ that is biased towards inserting newlines towards the beginning of the String – xrisk Jun 26 '15 at 12:09
  • @RishavKundu If you don't have performance issues, then could/should prefer better code. – Tom Jun 26 '15 at 12:09
  • 1
    *Randomly add newline if we haven't used too many*... ok... but the randomization of this is not equal distributed... first position has much more posibilities than last of having a `\n`.... – Jordi Castilla Jun 26 '15 at 12:09
  • @Tom in my opinion, _better_ is debatable here. StringTokenizer is discouraged because it doesn’t support regexes, but here, it’s perfectly reasonable to use it. I think performance should be considered more important in such a situation. – xrisk Jun 26 '15 at 12:21
  • There was no specification to the level of randomness, I don't think positional bias is a huge issue in this small brief @Jordi :P but I've mentioned it – Ross Drew Jun 26 '15 at 13:34
  • Thank you for the comment. Has this been tested ? because I got error... well.. I already stated that I want to create a new string with random new line "between" the words. If it got new line at the beginning of String, then the newline is not "between words"... Maybe the Random should specify the range between 2 until the text length... and where is text2's relation with sb.append?? because text2 is unused... – Lynx Jun 27 '15 at 07:07
  • I added text2 to my example – Ross Drew Jun 29 '15 at 16:03
1

First you need a new random from 2-4:

int max = 4;
int min = 2;

Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;

After split string into words:

String[] words = text.split(" ");

Then, get 4 different numbers from 1 to words.length

ArrayList<Integer> randomPositions = new ArrayList<Integer>(randomNum);
max = words.length;
min = 1;
for (int count = 0; count < randomNum; count ++) {
   int random = rand.nextInt((max - min) + 1) + min;
   if (randomPositions.contains(random)) count --;
   else randomPositions.add(random);
}

Finally put \n in positions when rebuilding the array:

StringBuilder result = new StringBuilder();
for (int count = 0; count < max; count ++) {
    result.append(words[count]);
    if (randomPositions.contains(count))
        result.append("\n");
    else
        result.append(" ");
}

Check this working demo

Output1:

Nothing right in my
brain. Nothing
left in my brain 

Output2:

Nothing right
in my brain. Nothing left
in my
brain 

Output3:

Nothing right in my brain. Nothing left
in my brain 
Jordi Castilla
  • 24,953
  • 6
  • 58
  • 97
  • Thank you for answering.. I did your solution. but each characters are entered.. like: N o t h i n g r i g h t how come? anyway .. what is the use of using that Array List? – Lynx Jun 26 '15 at 11:53
  • 1
    `ArrayList` is a `List` and it has possibilit of check the values inside... you can also create an array of integers `int[] positions` and check if the array contains by using a inner for loop or converting *on the fly* with: `Arrays.asList(positions).contains(count)` but it will cost much more CPU – Jordi Castilla Jun 26 '15 at 12:13
  • This one is better from before.. Notes, if you want to insert 2-4 new lines then the random should be between 1-3. Because the newline counts from 0,1,2,3 position... How can it cost more CPU?? Also, do you know how to prevent to add new line at the end of sentence? because sometimes it adds new line after last word, I only want new line "between words".. – Lynx Jun 27 '15 at 07:41
0

You can only get either the first index using indexOf() or the last index using lastIndexOf() methods.

But as a workaround you can use text.indexOf(" ", randomInt);. This will give you the first index of " " after the randomInt index.

Codebender
  • 13,431
  • 6
  • 40
  • 83
0

First you could get a random index where to put the new line

Random rand = new Random();
String[] words = text.split(' '); 

for(int i = 0; i < 3; i++){
    int index = rand.nextInt(words.length());
    words[index] =  "\n" + words[index];
}

text = Arrays.toString(words);

and at the end you will have 3 new lines on random places in your text string

EDIT: one way the result to be without commas is this one:

text = Arrays.toString(words).replaceAll(", ", " ");
Gabriella Angelova
  • 2,898
  • 1
  • 17
  • 29
  • Thank you for answering. This one can generate new line, but however the result becomes: [Nothing, right, in, my..... ] maybe it is because it is printed as arrays... is there any ways to make it become sentence with several lines? (without commas) – Lynx Jun 26 '15 at 12:07
  • o yes, you're right, I didn't get it. Try with my edit. I think it would result in what you need :) – Gabriella Angelova Jun 26 '15 at 12:10
0
String str = "Nothing right in my brain. Nothing left in my brain";
String[] split = str.split(" ");
for (int i = 0; i < split.length; i++) {
    int flag = ((int) (Math.random() * 10)) % 2;

    if (flag == 0) {
        split[i] = split[i] + "\n";
    }
}
str="";
for (int i = 0; i < split.length; i++) {
    str += split[i]+" ";
}
ValarDohaeris
  • 619
  • 1
  • 6
  • 21
0

Generate String with insertions at different positions:

public static String generateString(String inputString, String delimiter,
        String insString, int[] insIndexes) {

    String[] splittedString = inputString.split(delimiter);

    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < splittedString.length; i++) {

        sb.append(splittedString[i]);

        if (Arrays.binarySearch(insIndexes, i + 1) >= 0)
            sb.append(delimiter + insString);

        sb.append(delimiter);
    }

    return sb.toString();
}

Invocation Part :

    String inputString = "Nothing right in my brain. Nothing left in my brain";
    String delimiter = " "; // input String delimiter

    String insString = "\n"; // insertion String
    int[] insIndexes = { 2, 4, 6, 8 }; // insertion indexes

    String outputString = generateString(inputString, delimiter, insString, insIndexes);
Rajesh
  • 2,120
  • 1
  • 10
  • 14