Question

I am writing a mad libs program for fun and to just program something. The program itself is pretty straight forward, but I find myself resorting to several concatenations due to the nature of the game where you place user given words into a sentence. Is there an elegant work around to resort to less concatenations or even eliminate them for something more efficient? I know in the end it will make no difference if I use concatenations or not, but I am curious if there is a more elegant way to write this program.

Update: I am using java, but if there is a general solution to escaping concatenation that would be appreciated too.

Was it helpful?

Solution

One solution might be to write out your whole mad libs file and put in special tokens that need to be replaced by the words that are chosen.

You just bought a brand new ${NOUN1}, and it is going to ${VERB1} you.

Then you can use for example: String.replace("${NOUN1}", noun1) for all the words.

OTHER TIPS

Which language are you using?

Most high level langauges will have something similar to:

String.Format("{0} {1} {2} {3}", word1, word2, word3, word4);

There are two ways I can see you entirely avoiding concatenation in your game:

  1. Store the story template as as a collection of tokens: immutable parts and word placeholders. Then loop through the collection outputting immutable parts and user words instead of word placeholders.

  2. Write custom print class that will loop through the template string using charAt and output words instead of word placeholders.

Rather than calling String.replace for each word or constantly appending to a StringBuilder, you could put the words in an ordered array and use String.format ( in jdk 1.5 or newer ) or MessageFormat.format in jdk 1.4. Unfortunately the pattern formats for the two are different.

String myPattern = "My %s eats your %s";
// get values from the user here
String result = String.format( myPattern, (Object[])myArray );

or

String myPattern = "My {0} eats your {1}";
// get values from the user here
String result = MessageFormat.format( myPattern, (Object[])myArray );

Here is a complete program that fills in the string with values from the command line.

public class Format
{
    public static void main( String[] args )
    {
        String pattern = "My %s eats your %s";
        System.out.println( String.format( pattern, (Object[])args ));
    }
}

There're two aspects of your question.

First, you might wish to avoid using concatenations directly in your code. Then you can use some string-formatting routine from the runtime. This won't skip concatenations, but will move them from your code to the runtime.

Second, you may want to do concatenations more efficently. That's another story. The most important thing here is to preallocate the big enough buffer for the concatenated string, since memory reallocations are quite expensive. Copying substrings into the result strings are usually less expensive and are a necessary evil.

Nothing comes to my mind in terms of a general way to avoid concatenation. What you could do is to write yourself some kind of helper class which simplifies the job of concatenation for you. A suggestion I would like to give you however is to not directly concatenate strings as

String x = "Hi";
String y = x + " there!";

The implementation of string concatenation is quite slow in Java, so it's a better practice to use StringBuffer instead, especially if you do a lot of concatenations:

StringBuffer myStringBuffer = new StringBuffer();
myStringBuffer.append("Hi");
myStringBuffer.append(" there!");

Something like this. I didn't check this now in a compiler, but I'm sure you can figure it out yourself.

Not sure about Java but in some other languages such as PHP and Javascript creating an array and joining all of its elements can be faster.

Javascript example:

var str = str1 + str2 + str3 + "str4" + str5 + "str6" + str7;
var str = [str1, str2, str3, "str4", str5, "str6", str7].join("");

PHP example:

$str = $str1 . $str2 . $str3 . "str4" . $str5 . "str6" . $str7;
$str = implode("", array($str1, $str2, $str3, "str4", $str5, "str6", $str7));

This method is best if you want to put a delimiter between each string in which case it will not only be faster but more compact and readable.

By 'avoiding concatenation' I assume you mean allocating the space for the new string and assigning it? If you're on .NET then a StringBuilder should help some I think.

If you have a String an need to modify it very often, using a char[] array and creating a String when done modifying it might do the trick.

It's certainly possible to do this without concatenation if you want to. Although it's probably not very worthwhile.

It partly depends on where you're going to display the result. If it's on the web or the console, then you can write the result directly to an output stream.

So for example, if your template was something like "the %001 jumped out of the %002" you could:

1) scan the string to find where the variables are. 2) break the string into a list of components "the","jumped out of the", in this case 3) loop through the elements of your list and the results and dump them to output with something like this:

PrintStream  = //get output from somewhere
for(int i = 0; i < pieces.size()-1 ; i++){
   ps.print(peices.get(i));
   ps.print(answers.get(i));
}
ps.print(pieces.get(pieces.size()-1));//last one

Now. I don't know if you would call that 'elegant' or not. It would probably be kind of fast. Like I said, maybe appropriate if this was a web service and it became super popular, etc.

If this is a GUI app, you could write code to draw the strings separately, but that would probably take more time then concatenation.

but one thing you could do is use a ByteArrayOutputStream and pre-allocate enough space so that it could contain the filled out madlib without making additional allocations. That would be pretty quick as well.

Why do you want to avoid concatenation if its for cleanliness try lining it up nicely and it may end up looking surprisingly good.Even if you are worried about performance you may not need to use string builder, I believe that if you do a bunch of concatenations simply(ie "fdsfsd" + var1 +var2 +"dsfsdf" +"tyhty" it compiles to the same thing as string builder(effectively the same and looks cleaner). String Builder does make sense if you are concating a ton of stuff in a loop or with a complex flow.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top