c# finding characters between brackets - c#

I can't get it to work,
I need to get a character ex : i [L]ove [B]asketball and [H]ockey
i would like to take the L, B and H out of this string and show them in a console writeline
without using regex
I though about finding the position of [ with an indexof and add + 1 to get the letter and then replace the [ with something else ex: [ into &
so i could do a foreach bracket in that string... but i don't think it'll work o.O
Console.WriteLine("Characters are : ");
foreach(Brackets in sentence)..

string str = " i [L]ove [B]asketball and [H]ockey";
string[] array = str.Split('[');
foreach (var item in array)
{
if(item.Contains(']'))
Console.WriteLine(item[0]);
}
and you will get:
L
B
H
This would work as long as you don't have unpaired square brackets and there is a character between those square brackets.

You can do this without the split:
string str = " i [L]ove [B]asketball and [H]ockey";
for (int i = 0; i < str.Length; i++)
{
if(str[i] == '[')
Console.WriteLine(str[1 + i++]);
}

Using LINQ:
string s = "i [L]ove [B]asketball and [H]ockey";
var chars = s.Where((c, i) => i > 0 && s[i - 1] == '[' &&
i < s.Length - 1 && s[i + 1] == ']');
Equivalently:
var chars = Enumerable.Range(1, s.Length - 2)
.Where(i => s[i - 1] == '[' && s[i + 1] == ']')
.Select(i => s[i]);

You can use this regex to get the values between the brakets:
string input = "I [L]ove [B]asketball and [H]ockey";
var regex = new Regex(#"\[.*?\]");
var matches = regex.Matches(input);
foreach (var match in matches)
{
var letter = Regex.Replace(match.ToString(), #"\[|\]", string.Empty);
Console.WriteLine(letter);
}

With regex:
string str = " i [L]ove [B]asketball and [H]ockey";
Match match = Regex.Match(str, #"\[(.*?)\]");
StringBuilder sb = new StringBuilder();
//iterate over all matches
do
{
sb.Append(match);
match = match.NextMatch();
}while(match.Success); //condition
//note: Dump() only works in linqpad. Use Console.WriteLine() instead
sb.Dump();
//without brackets:
sb.ToString().Split(new []{'[',']'}, StringSplitOptions.RemoveEmptyEntries).Dump();

I have come up with lengthy code but it works with all the cases
Try This:
static void Main()
{
string line = "i [L]ove [B]asketball and [H]ockey";
int count = 0;
char temp=' ';
string str="";
foreach (char ch in line)
{
if (ch == '[')
{
count++;
}
else if (count ==1)
{
count++;
temp=ch;
}
else if(count==2 && ch==']')
{
str+=temp;
count=0;
}
else
{
count = 0;
}
}
Console.WriteLine(str);
}

Related

Split string at particular characters (C#)

What I want to do is to split an array and then put the character which i split at into another element
i.e. string text = "1*5+89-43&99" should become string[] textsplit = ["1","*","5","+","89","-","43","&","99"] (it must be a string)
and I will supply the characters to be left in seperate elements
You can do this using string.IndexOfAny.
Simply keep looking for the next index of any of the separators. When you find a separator, add the text between it and the last separator to your results, then look for the next separator.
string input = "1*1*5+89-43&33";
var separators = new[] { '+', '-', '*', '/', '&' };
var result = new List<string>();
int index;
int lastIndex = 0;
while ((index = input.IndexOfAny(separators, lastIndex)) != -1)
{
// Add the text before the separator, if there is any
if (index - lastIndex > 0)
{
result.Add(input.Substring(lastIndex, index - lastIndex));
}
// Add the separator itself
result.Add(input[index].ToString());
lastIndex = index + 1;
}
// Add any text after the last separator
if (lastIndex < input.Length)
{
result.Add(input.Substring(lastIndex));
}
Try with the following code snippet:
string text = "1*1*5+89-43&33";
List<string> textsplit = new List<string>();
foreach(var match in Regex.Matches(text, #"([*+/\-)(])|([0-9]+)"))
{
textsplit.Add(match.ToString());
}
Result added as an image.
Here's a basic and naive implementation that I beliewe will do what you want:
public static List<string> SplitExpression(string expression)
{
var parts = new List<string>();
bool isNumber(char c) => c == '.' || (c >= '0' && c <= '9');
bool isOperator(char c) => !isNumber(c);
int index = 0;
while (index < expression.Length)
{
char c = expression[index];
index++;
if (isNumber(c))
{
int numberIndex = index - 1;
while (index < expression.Length && isNumber(expression[index]))
index++;
parts.Add(expression.Substring(numberIndex, index - numberIndex));
}
else
parts.Add(c.ToString());
}
// move unary signs into following number
index = 0;
while (index < parts.Count - 1)
{
bool isSign = parts[index] == "-" || parts[index] == "+";
bool isFirstOrFollowingOperator = index == 0 || isOperator(parts[index - 1][0]);
bool isPriorToNumber = isNumber(parts[index + 1][0]);
if (isSign && isFirstOrFollowingOperator && isPriorToNumber)
{
parts[index + 1] = parts[index] + parts[index + 1];
parts.RemoveAt(index);
}
else
index++;
}
return parts;
}
Example input: "-1+-2*-10.1*.1", and output:
-1
+
-2
*
-10.1
*
.1

Identifing number of character/digits/special character in string

I want to calculate the summary of string in terms of number of alphabets, digits and special character in C#. For example:
String abc123$% should have summary like A3D3S2 (which means 3 Alphabet, 3 Digits and 2 Special character)
a34=$# should have summary like A1D2S3 (which means 1 Alphabet, 2 Digits and 3 Special character)
a3b$s should have summary like A1D1A1S1A1 (which means 1 Alphabet, 1 Digits,1 Alphabet, 1 Special character,1 Alphabet)
Can anyone guide me how can write an algorithm which can perform the above task in a quick way? as I think if I search the string character by character, then it will take considerable amount of time. and I have a large dataset of strings.
This works:
static string GetSummary(string input)
{
var sb = new StringBuilder();
string prevMode = "";
string curMode = "";
int sameModeCount = 0;
for (int i = 0; i <= input.Length; ++i)
{
if (i < input.Length)
{
char c = input[i];
if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')
{
curMode = "A";
}
else if ('0' <= c && c <= '9')
{
curMode = "D";
}
else
{
curMode = "S";
}
}
else
{
curMode = "";
}
if (curMode != prevMode && prevMode != "")
{
sb.Append(prevMode);
sb.Append(sameModeCount);
sameModeCount = 0;
}
prevMode = curMode;
++sameModeCount;
}
return sb.ToString();
}
Test:
public static void Main()
{
Console.WriteLine(GetSummary("abc123$%"));
Console.WriteLine(GetSummary("a34=$#"));
Console.WriteLine(GetSummary("a3b$s"));
}
Results:
A3D3S2
A1D2S3
A1D1A1S1A1
With Linq, you can do like this :
string myinput = "abc123$%";
int letter =0 , digit = 0, specialCharacter = 0;
myinput.ToCharArray().ToList().ForEach(x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ?
++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit,
specialCharacter);
You can directly use array in Linq ForEach without converting to list by :
Array.ForEach(myinput.ToCharArray(), x =>
{
letter = Char.IsLetter(x) ? ++letter : letter;
digit = Char.IsDigit(x) ? ++digit : digit;
specialCharacter = !Char.IsLetterOrDigit(x) ? ++specialCharacter : specialCharacter;
});
string formattedVal = String.Format("A{0}D{1}S{2}", letter, digit, specialCharacter);
This should work:
string s = "a3b$s";
char etype = 'X'; //current character's type
char etypeinit = 'X'; //tracker variable - holds type of last character
string str = "";
int count = 1;
foreach(char c in s)
{
//Use this block of conditionals to assign type for current character
if(char.IsLetter(c))
{
etype = 'A';
}
else if(char.IsDigit(c))
{
etype = 'D';
}
else
{
etype = 'S';
}
//This is a different type of character compared to the previous one
if(etypeinit != etype)
{
str += string.Format("{0}{1}",etype,count); //Build the string
count = 1; //Reset count
}
else
{
count++; //Increment because this is the same type as previous one
}
etypeinit = etype; //Set tracker variable to type of current character
}
Console.WriteLine(str);
Little late and little complex but able to produces all expected output as per given inputs in the question, please take a look:
string inputString = "abc123$%ab12";
var results = inputString.Select(x => char.IsLetter(x) ? 'A' :
char.IsDigit(x) ? 'D' : 'S');
StringBuilder outPutBuilder = new StringBuilder();
char previousChar = results.First();
int charCount = 0;
foreach (var item in results)
{
switch (item)
{
case 'A':
if (previousChar == 'A')
{
charCount++;
}
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
case 'D':
if (previousChar == 'D')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
default:
if (previousChar == 'S')
charCount++;
else
{
outPutBuilder.Append(previousChar.ToString() + charCount);
charCount = 1;
}
break;
}
previousChar = item;
}
outPutBuilder.Append(previousChar.ToString() + charCount);
Working example
Use a FOR loop to go through each character. If the character is in the range of a-z or A-Z then it is an alphabet. If in the range of 0-9 then it is a digit else special character.
Code
string inputStr = "a3b$s";
string outputStr = string.Empty;
char firstChar = Convert.ToChar(inputStr.Substring(0, 1));
outputStr = char.IsLetter(firstChar) ? "A1" : char.IsDigit(firstChar) ? "D1" : "S1";
for (int i = 1; i < inputStr.Length; i++)
{
char nextChar = char.IsLetter(inputStr[i]) ? 'A' :
char.IsDigit(inputStr[i]) ? 'D' : 'S';
char prevChar = Convert.ToChar(outputStr.Substring(outputStr.Length - 2, 1));
if (nextChar == prevChar)
{
int lastDig = Convert.ToInt32(outputStr.Substring(outputStr.Length - 1, 1));
outputStr = outputStr.Substring(0, outputStr.Length - 1) +
(lastDig + 1).ToString();
}
else
outputStr += nextChar.ToString() + "1";
}
Console.WriteLine(outputStr.ToString());
Output
A1D1A1S1A1
Find demo here

Split and append a string?

Right now I take in a string like this "112233 112233 112233 112233", and I split it into an array like this:
string text = ProcessString("112233 112233");
string[] dates = text.Split(' ');
And that works great, but I want to use string builder to build my string so they would end up like 11-22-33 11-22-33 etc.
So I did try this:
static string ProcessString(string input)
{
StringBuilder buffer = new StringBuilder(input.Length * 3 / 2);
for (int i = 0; i < input.Length; i++)
{
if ((i > 0) & (i % 2 == 0))
buffer.Append("-");
buffer.Append(input[i]);
}
return buffer.ToString();
}
It works, but it does not match the expected output of:
11-22-33
11-22-33
My current output is:
11-22-33-
1-12-23-3
-11-22-33
What can I do to fix this?
You can process a single string simply by iterating and collecting size-2 substrings of the string, and then joining them by the - character:
string s = "112233";
List<string> parts = new List<string>(s.Length / 2);
for (int i = 0; i < s.Length; i += 2)
parts.Add(s.Substring(i, 2));
Console.WriteLine(string.Join("-", parts)); // 11-22-33
So, for your full problem, you could do this:
static string ProcessString(string input)
{
var segments = input.Split(' ').Select(s =>
{
List<string> parts = new List<string>(s.Length / 2);
for (int i = 0; i < s.Length; i += 2)
parts.Add(s.Substring(i, 2));
return string.Join("-", parts);
});
return string.Join(" ", segments);
}
How about regex:
string s = "112233";
string pattern = #"\d{2}\B";
string result = Regex.Replace(s, pattern, m => m.Value + "-");
Can i offer you another Regex + LINQ approach?
var newDates = dates.Select(d => Regex.Replace(d, ".{2}", "$0-").Trim('-'));
string result = string.Join(" ", newDates);
But i like this extension more because it's readable and re-usable:
public static IEnumerable<String> SplitInParts(this String s, Int32 partLength)
{
if (s == null)
throw new ArgumentNullException("s");
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", "partLength");
for (var i = 0; i < s.Length; i += partLength)
yield return s.Substring(i, Math.Min(partLength, s.Length - i));
}
Then the code is even easier:
var newDates = dates.Select(d => string.Join("-", d.SplitInParts(2)));
string result = string.Join(" ", newDates);
I have this approach :
string input = "112233 445566 778899 101010";
string[] dates = input.Split(' ');
foreach (string date in dates){
Console.WriteLine(date);
string result = date.Substring(0, 2) + '-' + date.Substring(2, 2) + "-" + date.Substring(4, 2);
Console.WriteLine(result);
}
You can use Array.ConvertAll:
string str = "112233 112233 112233 112233";
string[] dates = str.Split();
dates = Array.ConvertAll(dates, s => s.Insert(4, "-").Insert(2, "-"));
foreach (var s in dates)
Console.WriteLine(s);

How to check if file contains strings, which will double repeat sign?

I would like to check if file containing some strings, separated with # contains double repeat sign. Example:
I have a file like this:
1234#224859#123567
I am reading this file and putting strings separated with # it into array.
I would like to find which strings have a digit repeated next to each other (in this case 224859) and return position of first digit that repeats in this string?
This is what I have so far:
ArrayList list = new ArrayList();
OpenFileDialog openFile1 = new OpenFileDialog();
int size = -1;
DialogResult dr = openFile1.ShowDialog();
string file = openFile1.FileName;
try
{
string text = File.ReadAllText(file);
size = text.Length;
string temp = "";
for (int i = 0; i < text.Length; i++)
{
if (text[i] != '#')
{
temp += text[i].ToString();
}
else
{
list.Add(temp);
temp = "";
}
}
}
catch (IOException)
{
}
string all_values = "";
foreach (Object obj in list)
{
all_values += obj.ToString() + " => ";
Console.WriteLine(" => ", obj);
}
textBox1.Text = (all_values);
This regex should do the trick.
var subject = "1234#224859#123567";
foreach(var item in subject.Split('#'))
{
var regex = new Regex(#"(?<grp>\d)\k<grp>");
var match =regex.Match(item);
if(match.Success)
{
Console.WriteLine("Index : {0}, Item:{1}", match.Index, item);
//prints Index : 0, Item:224859
}
}
This is a more procedural approach than Sriram's, but the main benefit is remembering your results in order to use them later in your program.
Basically, the string is split based on the # delimiter, which returns a string[] which holds each number inside. Then, for each string you iterate through the characters and check to see if the current character at i matches the next character at i + 1. If so, the earliest appearance of a duplicate digit is at i, so i is remembered and we break out of the loop that processes chars.
Since int is a non-nullable type, I decided to use -1 to indicate that a match was not found in a string.
Dictionary<string, int> results = new Dictionary<string, int>();
string text = "1234#224859#123567#11#4322#43#155";
string[] list = text.Split('#');
foreach (string s in list)
{
int tempResult = -1;
for (int i = 0; i < s.Length - 1; i++)
{
if(s.ElementAt(i) == s.ElementAt(i + 1))
{
tempResult = i;
break;
}
}
results.Add(s, tempResult);
}
foreach (KeyValuePair<string, int> pair in results)
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
Output:
1234: -1
224859: 0
123567: -1
11: 0
4322: 2
43: -1
155: 1
here's another Regex that works
int indexof = -1;
String input = "3492883#32280948093284#990303294";
string[] numbers = input.Split('#');
foreach(string n in numbers)
{
Match m=Regex.Match(n, #"(\d)\1+");
if (m.Success)
{
indexof = m.Index;
}
}
Would this do what you are looking for?
string text = File.ReadAllText(file);
string[] list = text.Split(new char[] { '#' });
Then, after you have the strings separated:
foreach (string s in list)
{
int pos = HasDoubleCharacter(s);
if (pos > -1)
{
// do something
}
}
private static int HasDoubleCharacter(string text)
{
int pos = 0;
char[] c3 = text.ToCharArray();
char lastChar = (char)0;
foreach (char c in c3)
{
if (lastChar == c)
return pos;
lastChar = c;
pos++;
}
return -1;
}
Or are you just looking for the list of positions of all doubles in the original text. If so (and you don't need to act on the various strings separately, you might try this:
private static List<int> FindAllDoublePositions(string text)
{
List<int> positions = new List<int>();
char[] ca = text.ToCharArray();
char lastChar = (char)0;
for (int pos = 0; pos < ca.Length; pos++)
{
if (Char.IsNumber(ca[pos]) && lastChar == ca[pos])
positions.Add(pos);
lastChar = ca[pos];
}
return positions;
}
If your looking for a specific string pattern, Regex is most likely to be your best friend :
string text = "1234#224859#123567asdashjehqwjk4234#244859#123567asdhajksdhqjkw1434#244859#123567";
var results = Regex.Matches(text, #"\d{4}#(?<Value>\d{6})#\d{4}");
var allValues = "";
foreach (Match result in results)
{
allValues = result.Groups["Value"].Value + " => ";
Console.WriteLine(" => ", result.Value);
}

C# Regular Expression to insert "_" after third, then seventh character with a new line after the eighth character

I was wondering if someone could help. I am trying to change a string in the below format:
goeirjew98rut34ktljre9t30t4j3der
to be outputted as below:
geo_irje_w
98r_ut34_k
tlj_re9t_3
0t4_j3de_r
So insert an underscore after the third and seventh characters and insert a new line after the eighth.
After doing some reading I thought the best way to do this might be via a regular expression such as the example at the below link:
http://msdn.microsoft.com/en-us/library/xwewhkd1(v=vs.110).aspx
However I am not sure how to modify this for my needs. Any help what so ever would be greatly appreciated.
Thanks
It can be easily solved by a regular expression and a Replace, like this:
var s = "goeirjew98rut34ktljre9t30t4j3der";
Regex.Replace(s, #"(\w{3})(\w{4})(\w{1})", "$1_$2_$3\n").Dump();
This is definitely something that is best solved with a quick loop:
string s = "goeirjew98rut34ktljre9t30t4j3der";
var outputs = new List<string>();
for (var i = 0; i < s.Length; i += 8)
{
string sub = s.Substring(i, Math.Min(8, s.Length - i));
if(sub.Length > 3)
sub = sub.Insert(3, "_");
if (sub.Length > 8)
sub = sub.Insert(8, "_");
outputs.Add(sub);
}
I think you can not insert char in string by this rule, but I hope this code be useful for you.
public string Decode(string str)
{
var state = 0;
var c = 0;
var newStr = string.Empty;
foreach (var ch in str)
{
c++;
newStr += ch;
if (state == 0 && c == 3)
{
newStr += "_";
state = 1;
c = 0;
}
if (state == 1 && c == 4)
{
newStr += "_";
state = 2;
c = 0;
}
if (state == 2 && c == 1)
{
newStr += "\r\n";
state = 0;
c = 0;
}
}
return newStr;
}
I would make it so u can change everything on the fly and use stringextentions
class Program
{
static void Main(string[] args)
{
string str = "goeirjew98rut34ktljre9t30t4j3der";
var parts = str.SplitInParts(8); //Split in different parts
foreach (var part in parts)
{
string formattedString = part.MultiInsert("_", 2, 6); //Insert your char on all position u want
Console.WriteLine(formattedString);
}
Console.ReadKey();
}
}
static class StringExtensions
{
public static IEnumerable<String> SplitInParts(this String s, Int32 partLength)
{
if (s == null)
throw new ArgumentNullException("s");
if (partLength <= 0)
throw new ArgumentException("Part length has to be positive.", "partLength");
for (var i = 0; i < s.Length; i += partLength)
yield return s.Substring(i, Math.Min(partLength, s.Length - i));
}
public static string MultiInsert(this string str, string insertChar, params int[] positions)
{
StringBuilder sb = new StringBuilder(str.Length + (positions.Length * insertChar.Length));
var posLookup = new HashSet<int>(positions);
for (int i = 0; i < str.Length; i++)
{
sb.Append(str[i]);
if (posLookup.Contains(i))
sb.Append(insertChar);
}
return sb.ToString();
}
}

Categories

Resources