I have a bunch of files in the format following like this:
20130201:14:58:47 I search: xx ('ID'= (xxxxxxxx) )
20130201:14:58:56 I request: search | For ID | Search
20130201:14:58:56 I search: xx ('ID'= (xxxxxxx) )
Is there something in C# like there is in python called a restkey? I want to grab the first three items (Date time, I (called an action), search/request) and insert each of those into their own column in an SQL table then in the 4th column put the rest of the line.
In python this was quite easy but I couldn't deal with all the hoops I had to jump through to get it to insert into my sql table. So I moved to C# where connection to SSMS is easier.
Although String.Split() is probably the nice and simple way around, I prefer using Regex for this kind of parsing. In this case a pattern like this:
(?<DateTime>\d{8}\:\d{2}\:\d{2}\:\d{2})\s(?<Action>\w)\s(?<SearchOrRequest>search|request)\:\s(?<RestOfTheLine>.*)
Gives you everything you need, nicely grouped into "DateTime", "Action", "SearchOrRequest" and "RestOfLine" match groups.
var pattern = "(?<DateTime>\d{8}\:\d{2}\:\d{2}\:\d{2})\s(?<Action>\w)\s(?<SearchOrRequest>search|request)\:\s(?<RestOfTheLine>.*)";
var regex = new Regex(pattern);
var match = regex.Match(inputString);
var theDate = match.Groups["DateTime"].Value;
var theAction = match.Groups["Action"].Value;
var theChoice = match.Groups["SearchOrRequest"].Value;
var theRest = match.Groups["RestOfTheLine"].Value;
Using string.Split method
string myString = "20130201:14:58:47 I search: xx (\'ID\'= (xxxxxxxx) )"
string[] strarr = myString.split(' ');
string theLetterIVariableThing = strarr[1];
string iddate = strarr[0];
StringBuilder sb = new StringBuilder();
for (int i = 1; i < strarr.Length; i++)
{
sb.Append(strarr[i]);
sb.Append(" ");
}
string trailingText = sb.ToString();
string id = iddate.split(':')[0];
sb.Clear();
for (int i = 1; i < 4; i++)
{
sb.Append(iddate.split(':'))[i];
}
string date = sb.ToString();
I think this will work, but it's probably the long way around.
You can do it using the .NET function String.Split().
Assuming your date string is of fixed-length, this should work:
//string inputStr = "20130201:14:58:47 I search: xx ('ID'= (xxxxxxxx) )";
//string inputStr = "20130201:14:58:56 I request: search | For ID | Search";
string inputStr = "20130201:14:58:56 I search: xx ('ID'= (xxxxxxx) )";
string dateStr = inputStr.Substring(0, 17);
string[] splitStr = inputStr.Substring(18).Split(new char[] { ':' });
string actionStr = splitStr[0].Substring(0, splitStr[0].IndexOf(' '));
string userStr = splitStr[0].Substring(2);
string restStr = splitStr[1].TrimStart();
// print out what we parsed
Console.WriteLine(inputStr);
Console.WriteLine(dateStr);
Console.WriteLine(actionStr);
Console.WriteLine(userStr);
Console.WriteLine(restStr);
Output:
20130201:14:58:56 I search: xx ('ID'= (xxxxxxx) )
20130201:14:58:56
I
search
xx ('ID'= (xxxxxxx) )
I tried a slightly different approach. I created a console program that can convert these files into fully qualified csv files. Then you can import into sql using ssms very easily.
static void Main(string[] args)
{
if (args.Length == 2)
{
using (StreamWriter sw = new StreamWriter(args[1]))
{
using (StreamReader sr = new StreamReader(args[0]))
{
String line;
while ((line = sr.ReadLine()) != null)
{
int index = 0;
int oldIndex = 0;
string dateTime = null;
string action = null;
string task = null;
string details = null;
index = line.IndexOf(' ', oldIndex);
dateTime = line.Substring(oldIndex, index - oldIndex);
oldIndex = index + 1;
index = line.IndexOf(' ', oldIndex);
action = line.Substring(oldIndex, index - oldIndex);
oldIndex = index + 1;
index = line.IndexOf(':', oldIndex);
task = line.Substring(oldIndex, index - oldIndex);
oldIndex = index + 1;
details = line.Substring(oldIndex + 1);
sw.WriteLine("\"{0}\",\"{1}\",\"{2}\",\"{3}\"", dateTime, action, task, details);
}
}
}
}
else
{
Console.WriteLine("Usage: program <input> <output>");
}
}
This is a case where a regular expression is probably the right thing to use.
var testVectors = new[]
{
"20130201:14:58:47 I search: xx ('ID'= (xxxxxxxx) )",
"20130201:14:58:56 I request: search | For ID | Search",
"20130201:14:58:56 I search: xx ('ID'= (xxxxxxx) )"
};
var expression = #"^(?<TimeStamp>[0-9]{8}(:[0-9]{2}){3}) (?<Action>[^ ]+) (?<Type>search|request): (?<Rest>.*)$";
var regex = new Regex(expression);
foreach (var testVector in testVectors)
{
var match = regex.Match(testVector);
Console.WriteLine(match.Groups["Timestamp"]);
Console.WriteLine(match.Groups["Action"]);
Console.WriteLine(match.Groups["Type"]);
Console.WriteLine(match.Groups["Rest"]);
}
The expression used makes some assumptions - what you called action is a sequence of characters not containing any spaces and only search and request are valid values for what I call type. But it should be easy to adopt the expression if any of the assumptions does not hold.
Related
ive got the following c# code:
string textBoxInput = richTextBox1.Text;
StreamReader SentencesFile = new StreamReader(#"C:\Users\Jeroen\Desktop\School\C#\opwegmetcsharp\answersSen.txt");
string Sentence = SentencesFile.ReadLine();
List<List<string>> keywordsList = new List<List<string>>();
List<string> outputSentence = new List<string>();
while (Sentence != null)
{
string keywords = Sentence.Substring(0, Sentence.IndexOf(' '));
string sentenceString = Sentence.Substring(0, Sentence.IndexOf(' ') +1);
List<string> splitKeyword = keywords.Split(',').ToList();
keywordsList.Add(splitKeyword);
outputSentence.Add(sentenceString);
}
int similar = 0;
int totalSimilar = 0;
List<string> SplitUserInput = textBoxInput.Split(' ').ToList();
And a .txt file which contains the following:
car,bmw Do you own a BMW?
car,Tesla Do you own a Tesla?
new,house Did you buy a new house?
snow,outside Is it snowing outside?
internet,down Is your internet down?
I can't figure out how i can compare every word that a user typed in the input (richTextBox1.Text) with the keywords in the .txt file ( like car and bmw for the first sentence )
And it also has to remember the sentence that has the highest amount of "hits".
I'm really stuck and searched a lot, but somehow i can't find out how i can do this.
A lot of thanks in advance!
You can use the LINQ Contains to check if a word is found in a list. But beware because it is case sensitive as password does. Use it like this:
//assuming you already list the keyword here
List<string> keywords = new List<string>() { "keyword1", "keyword2" };
Then for each sentence, supposing in this form:
string sentence1 = "Hi, this keYWord1 present! But quite malformed";
string sentence2 = "keywoRD2 and keyWOrd1 also present here, malformed";
Note: the above sentences could be your text from RichTextBox or file, it doesn't matter. Here I only show the concept.
You can do:
string[] words = sentence1.ToLower().Split(new char[] { ' ', ',', '.' });
int counter = 0;
for (int i = 0; i < words.Length; ++i){
counter += keywords.Contains(words[i]) ? 1 : 0;
}
And you can do likewise for sentence2. Whoever gets the highest counter has the highest hits.
This might be too advanced for a 1st year student but this piece of code will work for your need. Using Regex class to do matching for you. Performance-wise it's faster (AFAIK). I used a console application to work on this as I don't think it will be hard for you to use it in a WinForms/WPF application.
string textBoxInput = "car test do bmw"; // Just a sample as I am using a console app
string[] sentences = File.ReadAllLines("sentences.txt"); // Read all lines of a text file and assign it to a string array
string[] keywords = textBoxInput.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // Split textBoxInput by space
int[] matchArray = new int[sentences.Length];
for(int i = 0; i < sentences.Length; i++)
{
Regex regex = new Regex(#"\b(" + string.Join("|", keywords.Select(Regex.Escape).ToArray()) + #"+\b)", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(sentences[i]);
matchArray[i] = matches.Count;
}
int highesMatchIndex = Array.IndexOf(matchArray, matchArray.OrderByDescending(item => item).First());
Console.WriteLine("User input: " + textBoxInput);
Console.WriteLine("Matching sentence: " + sentences[highesMatchIndex]);
Console.WriteLine("Match count: " + matchArray[highesMatchIndex]);
Console.ReadLine();
I have some strings containing code for emoji icons, like :grinning:, :kissing_heart:, or :bouquet:. I'd like to process them to remove the emoji codes.
For example, given:
Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet:
I want to get this:
Hello , how are you? Are you fine?
I know I can use this code:
richTextBox2.Text = richTextBox1.Text.Replace(":kissing_heart:", "").Replace(":bouquet:", "").Replace(":grinning:", "").ToString();
However, there are 856 different emoji icons I have to remove (which, using this method, would take 856 calls to Replace()). Is there any other way to accomplish this?
You can use Regex to match the word between :anything:. Using Replace with function you can make other validation.
string pattern = #":(.*?):";
string input = "Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet: Are you super fan, for example. :words not to replace:";
string output = Regex.Replace(input, pattern, (m) =>
{
if (m.ToString().Split(' ').Count() > 1) // more than 1 word and other validations that will help preventing parsing the user text
{
return m.ToString();
}
return String.Empty;
}); // "Hello , how are you? Are you fine? Are you super fan, for example. :words not to replace:"
If you don't want to use Replace that make use of a lambda expression, you can use \w, as #yorye-nathan mentioned, to match only words.
string pattern = #":(\w*):";
string input = "Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet: Are you super fan, for example. :words not to replace:";
string output = Regex.Replace(input, pattern, String.Empty); // "Hello , how are you? Are you fine? Are you super fan, for example. :words not to replace:"
string Text = "Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet:";
i would solve it that way
List<string> Emoj = new List<string>() { ":kissing_heart:", ":bouquet:", ":grinning:" };
Emoj.ForEach(x => Text = Text.Replace(x, string.Empty));
UPDATE - refering to Detail's Comment
Another approach: replace only existing Emojs
List<string> Emoj = new List<string>() { ":kissing_heart:", ":bouquet:", ":grinning:" };
var Matches = Regex.Matches(Text, #":(\w*):").Cast<Match>().Select(x => x.Value);
Emoj.Intersect(Matches).ToList().ForEach(x => Text = Text.Replace(x, string.Empty));
But i'm not sure if it's that big difference for such short chat-strings and it's more important to have code that's easy to read/maintain. OP's question was about reducing redundancy Text.Replace().Text.Replace() and not about the most efficient solution.
I would use a combination of some of the techniques already suggested. Firstly, I'd store the 800+ emoji strings in a database and then load them up at runtime. Use a HashSet to store these in memory, so that we have a O(1) lookup time (very fast). Use Regex to pull out all potential pattern matches from the input and then compare each to our hashed emoji, removing the valid ones and leaving any non-emoji patterns the user has entered themselves...
public class Program
{
//hashset for in memory representation of emoji,
//lookups are O(1), so very fast
private HashSet<string> _emoji = null;
public Program(IEnumerable<string> emojiFromDb)
{
//load emoji from datastore (db/file,etc)
//into memory at startup
_emoji = new HashSet<string>(emojiFromDb);
}
public string RemoveEmoji(string input)
{
//pattern to search for
string pattern = #":(\w*):";
string output = input;
//use regex to find all potential patterns in the input
MatchCollection matches = Regex.Matches(input, pattern);
//only do this if we actually find the
//pattern in the input string...
if (matches.Count > 0)
{
//refine this to a distinct list of unique patterns
IEnumerable<string> distinct =
matches.Cast<Match>().Select(m => m.Value).Distinct();
//then check each one against the hashset, only removing
//registered emoji. This allows non-emoji versions
//of the pattern to survive...
foreach (string match in distinct)
if (_emoji.Contains(match))
output = output.Replace(match, string.Empty);
}
return output;
}
}
public class MainClass
{
static void Main(string[] args)
{
var program = new Program(new string[] { ":grinning:", ":kissing_heart:", ":bouquet:" });
string output = program.RemoveEmoji("Hello:grinning: :imadethis:, how are you?:kissing_heart: Are you fine?:bouquet: This is:a:strange:thing :to type:, but valid :nonetheless:");
Console.WriteLine(output);
}
}
Which results in:
Hello :imadethis:, how are you? Are you fine? This is:a:strange:thing :to type:,
but valid :nonetheless:
You do not have to replace all 856 emoji's. You only have to replace those that appear in the string. So have a look at:
Finding a substring using C# with a twist
Basically you extract all tokens ie the strings between : and : and then replace those with string.Empty()
If you are concerned that the search will return strings that are not emojis such as :some other text: then you could have a hash table lookup to make sure that replacing said found token is appropriate to do.
Finally got around to write something up. I'm combining a couple previously mentioned ideas, with the fact we should only loop over the string once. Based on those requirement, this sound like the perfect job for Linq.
You should probably cache the HashSet. Other than that, this has O(n) performance and only goes over the list once. Would be interesting to benchmark, but this could very well be the most efficient solution.
The approach is pretty straight forwards.
First load all Emoij in a HashSet so we can quickly look them up.
Split the string with input.Split(':') at the :.
Decide if we keep the current element.
If the last element was a match, keep the current element.
If the last element was no match, check if the current element matches.
If it does, ignore it. (This effectively removes the substring from the output).
If it doesn't, append : back and keep it.
Rebuild our string with a StringBuilder.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
static class Program
{
static void Main(string[] args)
{
ISet<string> emojiList = new HashSet<string>(new[] { "kissing_heart", "bouquet", "grinning" });
Console.WriteLine("Hello:grinning: , ho:w: a::re you?:kissing_heart:kissing_heart: Are you fine?:bouquet:".RemoveEmoji(':', emojiList));
Console.ReadLine();
}
public static string RemoveEmoji(this string input, char delimiter, ISet<string> emojiList)
{
StringBuilder sb = new StringBuilder();
input.Split(delimiter).Aggregate(true, (prev, curr) =>
{
if (prev)
{
sb.Append(curr);
return false;
}
if (emojiList.Contains(curr))
{
return true;
}
sb.Append(delimiter);
sb.Append(curr);
return false;
});
return sb.ToString();
}
}
}
Edit: I did something cool using the Rx library, but then realized Aggregate is the IEnumerable counterpart of Scan in Rx, thus simplifying the code even more.
If efficiency is a concern and to avoid processing "false positives", consider rewriting the string using a StringBuilder while skipping the special emoji tokens:
static HashSet<string> emojis = new HashSet<string>()
{
"grinning",
"kissing_heart",
"bouquet"
};
static string RemoveEmojis(string input)
{
StringBuilder sb = new StringBuilder();
int length = input.Length;
int startIndex = 0;
int colonIndex = input.IndexOf(':');
while (colonIndex >= 0 && startIndex < length)
{
//Keep normal text
int substringLength = colonIndex - startIndex;
if (substringLength > 0)
sb.Append(input.Substring(startIndex, substringLength));
//Advance the feed and get the next colon
startIndex = colonIndex + 1;
colonIndex = input.IndexOf(':', startIndex);
if (colonIndex < 0) //No more colons, so no more emojis
{
//Don't forget that first colon we found
sb.Append(':');
//Add the rest of the text
sb.Append(input.Substring(startIndex));
break;
}
else //Possible emoji, let's check
{
string token = input.Substring(startIndex, colonIndex - startIndex);
if (emojis.Contains(token)) //It's a match, so we skip this text
{
//Advance the feed
startIndex = colonIndex + 1;
colonIndex = input.IndexOf(':', startIndex);
}
else //No match, so we keep the normal text
{
//Don't forget the colon
sb.Append(':');
//Instead of doing another substring next loop, let's just use the one we already have
sb.Append(token);
startIndex = colonIndex;
}
}
}
return sb.ToString();
}
static void Main(string[] args)
{
List<string> inputs = new List<string>()
{
"Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet:",
"Tricky test:123:grinning:",
"Hello:grinning: :imadethis:, how are you?:kissing_heart: Are you fine?:bouquet: This is:a:strange:thing :to type:, but valid :nonetheless:"
};
foreach (string input in inputs)
{
Console.WriteLine("In <- " + input);
Console.WriteLine("Out -> " + RemoveEmojis(input));
Console.WriteLine();
}
Console.WriteLine("\r\n\r\nPress enter to exit...");
Console.ReadLine();
}
Outputs:
In <- Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet:
Out -> Hello , how are you? Are you fine?
In <- Tricky test:123:grinning:
Out -> Tricky test:123
In <- Hello:grinning: :imadethis:, how are you?:kissing_heart: Are you fine?:bouquet: This is:a:strange:thing :to type:, but valid :nonetheless:
Out -> Hello :imadethis:, how are you? Are you fine? This is:a:strange:thing :to type:, but valid :nonetheless:
Use this code I put up below I think using this function your problem will be solved.
string s = "Hello:grinning: , how are you?:kissing_heart: Are you fine?:bouquet:";
string rmv = ""; string remove = "";
int i = 0; int k = 0;
A:
rmv = "";
for (i = k; i < s.Length; i++)
{
if (Convert.ToString(s[i]) == ":")
{
for (int j = i + 1; j < s.Length; j++)
{
if (Convert.ToString(s[j]) != ":")
{
rmv += s[j];
}
else
{
remove += rmv + ",";
i = j;
k = j + 1;
goto A;
}
}
}
}
string[] str = remove.Split(',');
for (int x = 0; x < str.Length-1; x++)
{
s = s.Replace(Convert.ToString(":" + str[x] + ":"), "");
}
Console.WriteLine(s);
Console.ReadKey();
I'd use extension method like this:
public static class Helper
{
public static string MyReplace(this string dirty, char separator)
{
string newText = "";
bool replace = false;
for (int i = 0; i < dirty.Length; i++)
{
if(dirty[i] == separator) { replace = !replace ; continue;}
if(replace ) continue;
newText += dirty[i];
}
return newText;
}
}
Usage:
richTextBox2.Text = richTextBox2.Text.MyReplace(':');
This method show be better in terms of performance compare to one with Regex
I would split the text with the ':' and then build the string excluding the found emoji names.
const char marker = ':';
var textSections = text.Split(marker);
var emojiRemovedText = string.Empty;
var notMatchedCount = 0;
textSections.ToList().ForEach(section =>
{
if (emojiNames.Contains(section))
{
notMatchedCount = 0;
}
else
{
if (notMatchedCount++ > 0)
{
emojiRemovedText += marker.ToString();
}
emojiRemovedText += section;
}
});
I have a string
string a = "(something is there),xyz,(something there)";
and, I use this
string s = "(something is there),xyz,(something there)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);
but I want to use the second part (something there)
how can I do it?
a.Split("(),".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
This will return an array with 3 strings: something is there, xyz, and something there
Not sure what exactly you're doing around this, however this does it in this specific case:
var last = s.Split(',').Last(); // "(something there)"
Or more verbosely for explanation:
var s = "(something is there),xyz,(something there)";
var split = s.Split(','); // [ "(something is there)", "xyz", "(something there)" ]
var last = split.Last(); // "(something there)"
And if you don't want the brackets(en-GB)
var content = last.Trim('(', ')'); // "something there"
If "last" is the same as "second" in this case you can use String.LastIndexOf:
string lastPart = null;
int lastStartIndex = a.LastIndexOf('(');
if (lastStartIndex >= 0)
{
int lastEndIndex = a.LastIndexOf(')');
if (lastEndIndex >= 0)
lastPart = a.Substring(++lastStartIndex, lastEndIndex - lastStartIndex);
}
Here is a solution which extracts all tokens from the string into a List<string>:
int startIndex = -1, endIndex = -1;
var tokens = new List<string>();
while (true)
{
startIndex = a.IndexOf('(', ++endIndex);
if (startIndex == -1) break;
endIndex = a.IndexOf(')', ++startIndex);
if (endIndex == -1) break;
tokens.Add(a.Substring(startIndex, endIndex - startIndex));
}
So now you could use the indexer or Enumerable.ElementAtOrDefault:
string first = tokens[0];
string second = tokens.ElementAtOrDefault(1);
If the list is too small you get null as result. If you just want the last use tokens.Last().
You can use this:
string s = "(something is there),xyz,(something there)";
var start = s.Split(',')[2];
Also You can use:
string s = "(something is there),xyz,(something there)";
Regex regex = new Regex(#"\([^()]*\)(?=[^()]*$)");
Match match = regex.Match("(something is there),xyz,(something there)");
var result = match.Value;
You could use the following if you just want the text:
var s = "(something is there),xyz,(something there)";
var splits = s.Split('(');
var text = splits[2].Trim(')');
If you want to get the text between second '(' and ')' then use the second parameter of IndexOf which sets the starting index for searching
start = s.IndexOf("(", end) + 1;
end = s.IndexOf(")", start);
string secondResult = s.Substring(start, end - start);
If you want to get the string after the last ) use this code:
string otherPart = s.Substring(end+1);
So I have a string called today with the value "nick_george_james"
it looks like this
string today = "_nick__george__james_";
how can i isolate the text between the '_' into a new string? i want to get the 3 names into seperate strings so that in the end i have name1, name2, name3 with the values nick, george and james
my application is written in c#
use string.Split
string[] array = today.Split('_');
After editing your question, I realized that you have multiple _ in your string. You should try the following.
string[] array = today.Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
Or
string[] array = today.Split(new []{"_"}, StringSplitOptions.RemoveEmptyEntries);
Later your array will contain:
array[0] = "nick";
array[1] = "george";
array[2] = "james";
string[] array = today.Split('_');
name1=array[0];
name2=array[1];
name3=array[2];
Thought of coming up with an idea other than string.Split.
string today = "_nick__george__james_";
//Change value nNoofwordstobeFound accordingly
int nNoofwordstobeFound = 3;
int nstartindex = 0;
int nEndindex = 0;
int i=1;
while (i <= nNoofwordstobeFound)
{
Skip:
nstartindex = today.IndexOf("_",nEndindex);
nEndindex = today.IndexOf("_", nstartindex + 1);
string sName = today.Substring(nstartindex + 1, nEndindex - (nstartindex + 1));
if (sName == "")
{
goto Skip;
}
else
{
//Do your code
//For example
string abc= sName;
}
i++;
}
I'd still prefer string.split method over this anytime.
string[] nameArray = today.Split('_');
Here you will get a array of names. You can get each name from by specifying index positions of the nameArray.
ie Now the the nameArray contains values as below
nameArray[0] = "nick", nameArray[1] = "george", nameArray[2] = "james"
I must do a automatic codes generator with user-configurable string with predefined keys and can not find a good way to do it.
For example, a string
OT-{CustomCode}-{Date}-{##}
could generate codes
OT-C0001-20100420-01
OT-C0001-20100420-02
I thought of using RegExpr.Replace(), but I would have problems if the code of a customer was {##}
Any help is welcome! (and sorry for my english)
You can use string.Format():
string generated = string.Format("OT-{0}-{1}-{2}", code, date, num);
The {x} are placeholders for strings to be replaced.
Do you mean an auto-generated code definition is for example:
Foo {##} , Bar {Date}
and that will produce:
Foo 01 , Bar 20100420
Foo 02 , Bar 20100420
don't you ?
I think RegExpr.Replace() is a good solution, to the ## problem you can do something like this:
private void Generate()
{
Regex doubleSharpRegEx = new Regex("{#+}");
string customString = "Foo {####}";
string[] generatedCodes = new string[3];
for (int i = 0; i < generatedCodes.Length; i++)
{
string newString = doubleSharpRegEx.Replace(customString,
match =>
{
// Calculate zero padding for format
// remove brackets
string zeroPadding = match.Value.Substring(1, match.Value.Length - 2);
// replace # with zero
zeroPadding = zeroPadding.Replace('#', '0');
return string.Format("{0:" + zeroPadding + "}", i);
});
generatedCodes[i] = newString;
}
}
And the array generatedCodes contains:
Foo 0000
Foo 0001
Foo 0002
Foo 0003
EDIT:
Lambdas expression work only for framework 3.5.
If you need a solution for 2.0, you must only replace the lambda expression part with a delegate (obviously setting i available for the delegated method e.g. class member)
EDIT 2:
You can combine the 2 answer for example in the following code:
private void Generate2()
{
Regex customCodeRegex = new Regex("{CustomCode}");
Regex dateRegex = new Regex("{Date}");
Regex doubleSharpRegex = new Regex("{#+}");
string customString = "Foo-{##}-{Date}-{CustomCode}-{####}";
string newString = customCodeRegex.Replace(customString, "{0}");
newString = dateRegex.Replace(newString, "{1}");
newString = doubleSharpRegex.Replace(newString,
match =>
{
string zeroPadding = match.Value.Substring(1, match.Value.Length - 2);
zeroPadding = zeroPadding.Replace('#', '0');
return "{2:" + zeroPadding + "}";
});
string customCode = "C001";
string date = DateTime.Today.ToString("yyyyMMdd");
string[] generatedCodes = new string[3];
for (int i = 0; i < generatedCodes.Length; i++)
{
generatedCodes[i] = string.Format(newString, customCode, date, i);
}
}
The StringBuilder class provides an efficient replace:
string code = "C0001";
DateTime date = DateTime.Now;
int count = 1;
String formatString = "OT-{CustomCode}-{Date}-{##}";
StringBuilder sb = new StringBuilder(formatString);
sb.Replace("{CustomCode}", code);
sb.Replace("{Date}", date.ToString("yyyyMMdd"));
sb.Replace("{##}", count);
string result = sb.ToString();
But this is more useful if you're doing multiple replaces for the same tokens. Looks like you need String.Format as suggested by Elisha