I am writing a app in .NET which will generate random text based on some input. So if I have text like "I love your {lovely|nice|great} dress"
I want to choose randomly from lovely/nice/great
and use that in text. Any suggestions in C# or VB.NET are welcome.
views:
134answers:
4
+1
A:
String.Format("static text {0} more text {1}", randomChoice0, randomChoice1);
TreDubZedd
2010-06-01 19:34:58
this seems the easiest way but I will probably have to use more than 3 "tokens" in the string and string.format does not allow more than three
julio
2010-06-01 20:07:46
I think you're mistaken. String.Format() takes an arbitrary number of parameters/tokens. 'String.Format("{0}{1}{2}{3}", 0, 1, 2, 3)' results in '0123' without any errors.
TreDubZedd
2010-06-01 20:22:53
i meant i might need to use String.Format("{0}{1}{2}{3}{4}{5}", 0, 1, 2, 3,4,5)' which won't work
julio
2010-06-01 20:41:50
Have you even tried this? I just did, and successfully got the string '012345' without any errors. In fact, I also successfully tried 'String.Format("{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a')'.
TreDubZedd
2010-06-01 20:46:06
sorry, I was relying on intellisense which made me thing only 3 arguments can be used
julio
2010-06-01 20:50:57
A:
write a simple parser that will get the information in the braces, split it with string.Split
, get a random index for that array and build up the string again.
use the StringBuilder
for building the result due to performance issues with other stringoperations.
Jack
2010-06-01 19:35:22
+7
A:
You could do it using a regex to make a replacement for each {...}
. The Regex.Replace
function can take a MatchEvaluator
which can do the logic for selecting a random value from the choices:
Random random = new Random();
string s = "I love your {lovely|nice|great} dress";
s = Regex.Replace(s, @"\{(.*?)\}", match => {
string[] options = match.Groups[1].Value.Split('|');
int index = random.Next(options.Length);
return options[index];
});
Console.WriteLine(s);
Example output:
I love your lovely dress
Update: Translated to VB.NET automatically using .NET Reflector:
Dim random As New Random
Dim s As String = "I love your {lovely|nice|great} dress"
s = Regex.Replace(s, "\{(.*?)\}", Function (ByVal match As Match)
Dim options As String() = match.Groups.Item(1).Value.Split(New Char() { "|"c })
Dim index As Integer = random.Next(options.Length)
Return options(index)
End Function)
Mark Byers
2010-06-01 19:38:12
would it be possible to convert this code to vb.net ? it seems that it will perfectly suit my needs
julio
2010-06-01 20:05:18
+1 this is similar to how I've solved this before. I thought this looked familiar, more so now after the VB request (see http://social.msdn.microsoft.com/Forums/en/regexp/thread/51628ff3-23f9-4de5-bf42-1baef802b8c7) - makes me wonder if this is h/w. My pattern differed slightly to ensure a `|` but `.*?` works just as well :)
Ahmad Mageed
2010-06-01 21:35:38
@julio, @Mark: you might already know this but multi-statement lambdas were introduced in VB10 (unlike C# which had it earlier). I can't test the translation at the moment but wanted to point that out (Reflector might not be accurate). I had used `AddressOf` instead and broke it out as its own method for the `MatchEvaluator`. For VB10+ a multi-statement lambda is the way to go.
Ahmad Mageed
2010-06-01 21:50:00
@julio glad that helped but please consider marking @Mark's reply as the answer since he had the right solution that helped you.
Ahmad Mageed
2010-06-02 14:00:44
+2
A:
This may be a bit of an abuse of the custom formatting functionality available through the ICustomFormatter and IFormatProvider interfaces, but you could do something like this:
public class ListSelectionFormatter : IFormatProvider, ICustomFormatter
{
#region IFormatProvider Members
public object GetFormat(Type formatType)
{
if (typeof(ICustomFormatter).IsAssignableFrom(formatType))
return this;
else
return null;
}
#endregion
#region ICustomFormatter Members
public string Format(string format, object arg, IFormatProvider formatProvider)
{
string[] values = format.Split('|');
if (values == null || values.Length == 0)
throw new FormatException("The format is invalid. At least one value must be specified.");
if (arg is int)
return values[(int)arg];
else if (arg is Random)
return values[(arg as Random).Next(values.Length)];
else if (arg is ISelectionPicker)
return (arg as ISelectionPicker).Pick(values);
else
throw new FormatException("The argument is invalid.");
}
#endregion
}
public interface ISelectionPicker
{
string Pick(string[] values);
}
public class RandomSelectionPicker : ISelectionPicker
{
Random rng = new Random();
public string Pick(string[] values)
{
// use whatever logic is desired here to choose the correct value
return values[rng.Next(values.Length)];
}
}
class Stuff
{
public static void DoStuff()
{
RandomSelectionPicker picker = new RandomSelectionPicker();
string result = string.Format(new ListSelectionFormatter(), "I am feeling {0:funky|great|lousy}. I should eat {1:a banana|cereal|cardboard}.", picker, picker);
}
}
Dr. Wily's Apprentice
2010-06-01 20:08:30