Is there a way to get the string between.. lets say quote "
The problem with using Indexof and substring is that it gets the first " and last " but not the pair. Like
"Hello" "WHY ARE" "WWWWWEEEEEE"
It will get
Hello" "WHY ARE" "WWWWWEEEEEE
I want it to get to array > Hello, WHY ARE, WWWWEEEEEE
Is there any way to do this?
Something like this?
StringCollection resultList = new StringCollection();
try
{
Regex regexObj = new Regex("\"([^\"]+)\"");
Match matchResult = regexObj.Match(subjectString);
while (matchResult.Success)
{
resultList.Add(matchResult.Groups[1].Value);
matchResult = matchResult.NextMatch();
}
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
If subjectString was "Hello" "WHY ARE" "WWWWWEEEEEE", that should give you a list containing:
Hello
WHY ARE
WWWWWEEEEEE
A more compact example which uses the static Regex class instead, and just writes the matches to console instead of adding to a collection:
var subject = "\"Hello\" \"WHY ARE\" \"WWWWWEEEEEE\"";
var match = Regex.Match(subject, "\"([^\"]+)\"");
while (match.Success)
{
Console.WriteLine(match.Groups[1].Value);
match = match.NextMatch();
}
string s = '"Hello" "WHY ARE" "WWWWWEEEEEE"'
string[] words = s.Split('"');
// words is now ["Hello", " ", "WHY ARE", " ", "WWWWWEEEEEE"]
If you don't want the empty strings, you can split by '" "', in which case you will get ['"Hello', "WHY ARE", 'WWWWWEEEEEE"'].
On the other hand, using regular expressions could be the best solution for what you want. I'm not a C# expert, so I can't give the code from the top of my head, but this is the regex you'll want to use: "(.*?)"
You can also use the String.IndexOf(char value, int startIndex) method which has, as its parameter says, a start index from which the scan is started.
int start = 0;
do
{
int i1 = s.IndexOf('=', start);
if (i1 < 0) break;
int i2 = s.IndexOf('=', i1 + 1);
if (i2 < 0) break;
yield return s.Substring(i1, i2 - i1);
start = i2 + 1;
}
while (start < s.Length);
string s = '"Hello" "WHY ARE" "WWWWWEEEEEE"
s.replace("\" \"", "!*!"); // custom seperator
s.Replace('"', string.empty);
string[] words = s.Split('!*!');
Should do the trick,
Kindness,
Dan
Related
I've got a project I'm working on in C#. I've got two char array's. One is a sentence and one is a word. I've got to iterate through the sentence array until I find a word that matches the word that was turned into an word array what I'm wondering is once I find the word how do I iterate backwards through the sentence array at the point I found the word back through the same length as the word array?
Code :
String wordString = "(Four)";
String sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
char[] wordArray = wordString.ToCharArray();
List<String> words = sentenceString.Split(' ').ToList<string>();
//This would be the part where I iterate through sentence
foreach (string sentence in sentArray)
{
//Here I would need to find where the string of (Four) and trim it and see if it equals the wordString.
if (sentence.Contains(wordString)
{
//At this point I would need to go back the length of wordString which happens to be four places but I'm not sure how to do this. And for each word I go back in the sentence I need to capture that in another string array.
}
I don't know if I'm being clear enough on this but if I'm not please feel free to ask.. Thank you in advanced. Also what this should return is "fowl of Uruguay repeaters". So basically the use case is for the number of letters in the parenthesis the logic should return the same number of words before the word in parenthesis.
our are you. I have few question concerned to this exercise.
If the Word (four) was in beginning it should not return? or return all string?
As the length of four is equal to 4 imagine if that word appear as the second word on sentence what it should return just the first word or return 4 words even including the (four) word.?
My solution is the laziest one I just see your question and decide to help.
My solution assumes it return all the word before the (four) if the length is bigger than the word before the (four) word.
My solution return empty string if the word (four) is in the beginning.
My solution return Length of (four) (4) words before (four) word.
ONCE AGAIN IT IS NOT MY BEST APPROACH.
I see the code bellow:
string wordString = "(Four)";
string sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
//Additionally you can add splitoption to remove the empty word on split function bellow
//Just in case there are more space in sentence.
string[] splitedword = sentenceString.Split(' ');
int tempBackposition = 0;
int finalposition = 0;
for (int i = 0; i < splitedword.Length; i++)
{
if (splitedword[i].Contains(wordString))
{
finalposition = i;
break;
}
}
tempBackposition = finalposition - wordString.Replace("(","").Replace(")","").Length;
string output = "";
tempBackposition= tempBackposition<0?0:tempBackposition;
for (int i = tempBackposition; i < finalposition; i++)
{
output += splitedword[i] + " ";
}
Console.WriteLine(output);
Console.ReadLine();
If it's not what you want can you answer my questions on top? or help me to understand were it's wrong
int i ;
string outputString = (i=sentenceString.IndexOf(wordString))<0 ?
sentenceString : sentenceString.Substring(0,i) ;
var wordString = "(Four)";
int wordStringInt = 4; // Just do switch case to convert your string to int
var sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
var sentenceStringArray = sentenceString.Split(' ').ToList();
int wordStringIndexInArray = sentenceStringArray.IndexOf(wordString) - 1;
var stringOutPut = "";
if (wordStringIndexInArray > 0 && wordStringIndexInArray > wordStringInt)
{
stringOutPut = "";
while (wordStringInt > 0)
{
stringOutPut = sentenceStringArray[wordStringInt] + " " + stringOutPut;
wordStringInt--;
}
}
What you are matching is kind of complex, so for a more general solution you could use regular expressions.
First we declare what we are searching for:
string word = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
We will then search for the words in this string using regular expressions. Since we don't want to match whitespace, and we need to know where each match actually starts and we need to know the word inside the parenthesis we tell it that we optionally want opening and ending parenthesis, but we also want the contents of those as a match:
var words = Regex.Matches(sentence, #"[\p{Ps}]*(?<Content>[\w]+)[\p{Pe}]*").Cast<Match>().ToList();
[\p{Ps}] means we want opening punctuation ([{ etc. while the * indicates zero or more.
Followed is a sub-capture called Content (specified by ?<Content>) with one or more word characters.
At the end we specify that we want zero or more ending punctuation.
We then need to find the word in the list of matches:
var item = words.Single(x => x.Value == word);
Then we need to find this item's index:
int index = words.IndexOf(item);
At this point we just need to know the length of the contents:
var length = item.Groups["Content"].Length;
This length we use to go back in the string 4 words
var start = words.Skip(index - length).First();
And now we have everything we need:
var result = sentence.Substring(start.Index, item.Index - start.Index);
Result should contain fowl of Uruguay repeaters.
edit: It may be a lot simpler to just figure out the count from the word rather than from the content. In that case the complete code should be the following:
string word = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
var wordMatch = Regex.Match(word, #"[\p{Ps}]*(?<Content>[\w]+)[\p{Pe}]*");
var length = wordMatch.Groups["Content"].Length;
var words = Regex.Matches(sentence, #"\S+").Cast<Match>().ToList();
var item = words.Single(x => x.Value == word);
int index = words.IndexOf(item);
var start = words.Skip(index - length).First();
var result = sentence.Substring(start.Index, item.Index - start.Index);
\S+ in this case means "match one or more non-whitespace character".
You should try something like the following, which uses Array.Copy after it finds the number word. You will still have to implement the ConvertToNum function correctly (it is hardcoded in for now), but this should be a quick and easy solution.
string[] GetWords()
{
string sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
string[] words = sentenceString.Split();
int num = 0;
int i; // scope of i should remain outside the for loop
for (i = 0; i < words.Length; i++)
{
string word = words[i];
if (word.StartsWith("(") && word.EndsWith(")"))
{
num = ConvertToNum(word.Substring(1, word.Length - 1));
// converted the number word we found, so we break
break;
}
}
if (num == 0)
{
// no number word was found in the string - return empty array
return new string[0];
}
// do some extra checking if number word exceeds number of previous words
int startIndex = i - num;
// if it does - just start from index 0
startIndex = startIndex < 0 ? 0 : startIndex;
int length = i - startIndex;
string[] output = new string[length];
Array.Copy(words, startIndex, output, 0, length);
return output;
}
// Convert the number word to an integer
int ConvertToNum(string numberStr)
{
return 4; // you should implement this method correctly
}
See - Convert words (string) to Int, for help implementing the ConvertToNum solution. Obviously it could be simplified depending on the range of numbers you expect to deal with.
Here is my solution, im not using regex at all, for the sake of easy understanding:
static void Main() {
var wordString = "(Four)";
int wordStringLength = wordString.Replace("(","").Replace(")","").Length;
//4, because i'm assuming '(' and ')' doesn't count.
var sentenceString = "Maybe the fowl of Uruguay repeaters (Four) will be found";
//Transform into a list of words, ToList() to future use of IndexOf Method
var sentenceStringWords = sentenceString.Split(' ').ToList();
//Find the index of the word in the list of words
int wordIndex = sentenceStringWords.IndexOf(wordString);
//Get a subrange from the original list of words, going back x Times the legnth of word (in this case 4),
var wordsToConcat = sentenceStringWords.GetRange(wordIndex-wordStringLength, wordStringLength);
//Finally concat the output;
var outPut = string.Join(" ", wordsToConcat);
//Output: fowl of Uruguay repeaters
}
I have a solution for you:
string wordToMatch = "(Four)";
string sentence = "Maybe the fowl of Uruguay repeaters (Four) will be found";
if (sentence.Contains(wordToMatch))
{
int length = wordToMatch.Trim(new[] { '(', ')' }).Length;
int indexOfMatchedWord = sentence.IndexOf(wordToMatch);
string subString1 = sentence.Substring(0, indexOfMatchedWord);
string[] words = subString1.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
var reversed = words.Reverse().Take(length);
string result = string.Join(" ", reversed.Reverse());
Console.WriteLine(result);
Console.ReadLine();
}
Likely this can be improved regardng performance, but I have a feeling you don't care about that. Make sure you are using 'System.Linq'
I assumed empty returns when input is incomplete, feel free to correct me on that. Wasn't 100% clear in your post how this should be handled.
private string getPartialSentence(string sentence, string word)
{
if (string.IsNullOrEmpty(sentence) || string.IsNullOrEmpty(word))
return string.Empty;
int locationInSentence = sentence.IndexOf(word, StringComparison.Ordinal);
if (locationInSentence == -1)
return string.Empty;
string partialSentence = sentence.Substring(0, locationInSentence);
string[] words = partialSentence.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
int nbWordsRequired = word.Replace("(", "").Replace(")", "").Length;
if (words.Count() >= nbWordsRequired)
return String.Join(" ", words.Skip(words.Count() - nbWordsRequired));
return String.Join(" ", words);
}
I went with using an enumeration and associated dictionary to pair the "(Four)" type strings with their integer values. You could just as easily (and maybe easier) go with a switch statement using
case "(Four)": { currentNumber = 4; };
I feel like the enum allows a little more flexibility though.
public enum NumberVerb
{
one = 1,
two = 2,
three = 3,
four = 4,
five = 5,
six = 6,
seven = 7,
eight = 8,
nine = 9,
ten = 10,
};
public static Dictionary<string, NumberVerb> m_Dictionary
{
get
{
Dictionary<string, NumberVerb> temp = new Dictionary<string, NumberVerb>();
temp.Add("(one)", NumberVerb.one);
temp.Add("(two)", NumberVerb.two);
temp.Add("(three)", NumberVerb.three);
temp.Add("(four)", NumberVerb.four);
temp.Add("(five)", NumberVerb.five);
temp.Add("(six)", NumberVerb.six);
temp.Add("(seven)", NumberVerb.seven);
temp.Add("(eight)", NumberVerb.eight);
temp.Add("(nine)", NumberVerb.nine);
temp.Add("(ten)", NumberVerb.ten);
return temp;
}
}
static void Main(string[] args)
{
string resultPhrase = "";
// Get the sentance that will be searched.
Console.WriteLine("Please enter the starting sentance:");
Console.WriteLine("(don't forget your keyword: ie '(Four)')");
string sentance = Console.ReadLine();
// Get the search word.
Console.WriteLine("Please enter the search keyword:");
string keyword = Console.ReadLine();
// Set the associated number of words to backwards-iterate.
int currentNumber = -1;
try
{
currentNumber = (int)m_Dictionary[keyword.ToLower()];
}
catch(KeyNotFoundException ex)
{
Console.WriteLine("The provided keyword was not found in the dictionary.");
}
// Search the sentance string for the keyword, and get the starting index.
Console.WriteLine("Searching for phrase...");
string[] words = sentance.Split(' ');
int searchResultIndex = -1;
for (int i = 0; (searchResultIndex == -1 && i < words.Length); i++)
{
if (words[i].Equals(keyword))
{
searchResultIndex = i;
}
}
// Handle the search results.
if (searchResultIndex == -1)
{
resultPhrase = "The keyword was not found.";
}
else if (searchResultIndex < currentNumber)
{
// Check the array boundaries with the given indexes.
resultPhrase = "Error: Out of bounds!";
}
else
{
// Get the preceding words.
for (int i = 0; i < currentNumber; i++)
{
resultPhrase = string.Format(" {0}{1}", words[searchResultIndex - 1 - i], resultPhrase);
}
}
// Display the preceding words.
Console.WriteLine(resultPhrase.Trim());
// Exit.
Console.ReadLine();
}
I want to find the number of occurrence of particular word in a string.
I have searched online and found many answers like
Stack Overflow Answer
Answer from DotNetPerl
But none of them gave me accurate result.
What I want is:
Input:
I have asked the question in StackOverflow. Therefore i can expect answer here.
Output for "The" keyword:
The keyword count: 2
Note: It should not consider "The" from "Therefore" in a sentence.
Basically I want to match whole word and get the count.
Try like this
var searchText=" the ";
var input="I have asked the question in StackOverflow. Therefore i can expect answer here.";
var arr=input.Split(new char[]{' ','.'});
var count=Array.FindAll(arr, s => s.Equals(searchText.Trim())).Length;
Console.WriteLine(count);
DOTNETFIDDLE
EDIT
For your Search Sentence
var sentence ="I have asked the question in StackOverflow. Therefore i can expect answer here.";
var searchText="have asked";
char [] split=new char[]{',',' ','.'};
var splitSentence=sentence.ToLower().Split(split);
var splitText=searchText.ToLower().Split(split);
Console.WriteLine("Search Sentence {0}",splitSentence.Length);
Console.WriteLine("Search Text {0}",splitText.Length);
var count=0;
for(var i=0;i<splitSentence.Length;i++){
if(splitSentence[i]==splitText[0]){
var index=i;
var found=true;
var j=0;
for( j=0;j<splitText.Length;j++){
if(splitSentence[index++]!=splitText[j])
{
found=false;
break;
}
}
if(found){
Console.WriteLine("Index J {0} ",j);
count++;
i= index >i ? index-1 : i;
}
}
}
Console.WriteLine("Total found {0} substring",count);
DOTNETFIDDLE
A possible solution would be using Regex:
var count = Regex.Matches(input.ToLower(), String.Format("\b{0}\b", "the")).Count;
try Like this (Way 1)
string SpecificWord = " the ";
string sentence = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
int count = 0;
foreach (Match match in Regex.Matches(sentence, SpecificWord, RegexOptions.IgnoreCase))
{
count++;
}
Console.WriteLine("{0}" + " Found " + "{1}" + " Times", SpecificWord, count);
or Like this (Way 2)
string SpecificWord = " the ";
string sentence = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
int WordPlace = sentence.IndexOf(SpecificWord);
Console.WriteLine(sentence);
int TimesRep;
for (TimesRep = 0; WordPlace > -1; TimesRep++)
{
sentence = (sentence.Substring(0, WordPlace) +sentence.Substring(WordPlace +SpecificWord.Length)).Replace(" ", " ");
WordPlace = sentence.IndexOf(SpecificWord);
}
Console.WriteLine("this word Found " + TimesRep + " time");
You can use while loop to search index of the first occurrence, after that give search from found index ++ position and set one counter at the end of the loop. While loop goes untill index == -1.
Well the problem is not that simple you may think; there are many issues should be taken care of such as punctuation, letter case, and things like how word boundaries are identified.
However using N_Gram concept I provide the following solution:
1- Identify how many words are in the key. Name it as N
2- Extract all N-consecutive sequence of words (N_Grams) in the text.
3- Count the occurrence of key in N_Grams
string text = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
string key = "the question";
int gram = key.Split(' ').Count();
var parts = text.Split(' ');
List<string> n_grams = new List<string>();
for (int i = 0; i < parts.Count(); i++)
{
if (i <= parts.Count() - gram)
{
string sequence = "";
for (int j = 0; j < gram; j++)
{
sequence += parts[i + j] + " ";
}
if (sequence.Length > 0)
sequence = sequence.Remove(sequenc.Count() - 1, 1);
n_grams.Add(sequence);
}
}
// The result
int count = n_grams.Count(p => p == key);
}
For example for the key = the question and considering single space as word boundaries, the following bi-grams are extracted:
I have
have asked
asked the
the question
question in
in StackOverflow.
StackOverflow. Therefore
Therefore i
i can
can expect
expect answer
answer here.
and the number of times the question appears in the text is not obvious to see: 1
This solution should work wherever the string is:
var str = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
var numMatches = Regex.Matches(str.ToUpper(), "THE")
.Cast<Match>()
.Count(match =>
(match.Index == 0 || str[match.Index - 1] == ' ') &&
(match.Index + match.Length == str.Length ||
!Regex.IsMatch(
str[match.Index + match.Length].ToString(),
"[a-zA-Z]")));
.NET Fiddle
string input = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
string pattern = #"\bthe\b";
var matches = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
Console.WriteLine(matches.Count);
See Regex Anchors - "\b".
Try like this
string Text = "I have asked the question in StackOverflow. Therefore i can expect answer here.";
Text = Text.ToLower();
Dictionary<string, int> frequencies = null;
frequencies = new Dictionary<string, int>();
string[] words = Regex.Split(Text, "\\W+");
foreach (string word in words)
{
if (frequencies.ContainsKey(word))
{
frequencies[word] += 1;
}
else
{
frequencies[word] = 1;
}
}
foreach (KeyValuePair<string, int> entry in frequencies)
{
string word = entry.Key;
int frequency = entry.Value;
Response.Write(word.ToString() + "," + frequency.ToString()+"</br>");
}
And To search Specific Word then try Like This.
string Text = "I have asked the question in StackOverflow. Therefore the i can expect answer here.";
Text = Text.ToLower();
string searchtext = "the";
searchtext = searchtext.ToLower();
string[] words = Regex.Split(Text, "\\W+");
foreach (string word in words)
{
if (searchtext.Equals(word))
{
count = count + 1;
}
else
{
}
}
Response.Write(count);
There are many possibility for Count occurrence of whole word in a string.
E.g.
First:
string name = "pappu kumar sdffnsd sdfnsdkfbsdf sdfjnsd fsdjkn fsdfsd sdfsd pappu kumar";
var res= name.Contains("pappu kumar");
var splitval = name.Split("pappu kumar").Length-1;
Second:
var r = Regex.Matches(name, "pappu kumar").Count;
What about (seems more efficency then other solutions):
public static int CountOccurences(string haystack, string needle)
{
return (haystack.Length - haystack.Replace(needle, string.Empty).Length) / needle.Length;
}
Try out this works for structured data as well.
var splitStr = inputStr.Split(' ');
int result_count = splitStr.Count(str => str.Contains("userName"));
How can I search for a word within a string ?
I have one text box which the user insert a string and another on with with text just some random text.
Are there any alterative ways of doing this besides using regex and IndexOf? Like using a for loop and checking the length and character in the word.
This is what I tried so far
int i = 0;
int count = 0;
input2.Trim();
while ((i = input2.IndexOf(input1, i)) != -1)
{
i = i + input1.Length;
count++;
}
MessageBox.Show(count.ToString() + " Matches Found");
Looks like you want to get the Count of search string in the text. You can try the following.
string searchString = "TEST";
string completeText = "Some sentence TEST with other words incluing TEST";
int count = completeText.Split(new string[]{"TEST"},StringSplitOptions.None)
.Count() - 1;
MessageBox.Show(count.ToString() + " Matches Found");
Use a regex to match the number of occurances,
string test = "THE DOG WENT TO TOWN DOG";
int j = Regex.Matches(test, "DOG").Cast<Match>().Count();
I have a set of strings that contain within them one or more question marks delimited by a comma, a comma plus one or more spaces, or potentially both. So these strings are all possible:
BOB AND ?
BOB AND ?,?,?,?,?
BOB AND ?, ?, ? ,?
BOB AND ?,? , ?,?
?, ? ,? AND BOB
I need to replace the question marks with #P#, so that the above samples would become:
BOB AND #P1
BOB AND #P1,#P2,#P3,#P4,#P5
BOB AND #P1,#P2,#P3,#P4
BOB AND #P1,#P2,#P3,#P4
#P1,#P2,#P3 AND BOB
What's the best way to do this without regex or Linq?
I ignored the trimming of spaces in your output example, because if this is to be used in a SQL statement, the spaces are irrelevent. This should perform pretty well due to the use of StringBuilder rather than repeated calls to Replace, Substring, or other string methods.:
public static string GetParameterizedString(string s)
{
var sb = new StringBuilder();
var sArray = s.Split('?');
for (var i = 0; i < sArray.Length - 1; i++)
{
sb.Append(sArray[i]);
sb.Append("#P");
sb.Append(i + 1);
}
sb.Append(sArray[sArray.Length - 1]);
return sb.ToString();
}
If you don't want regex or LINQ, I would just write a loop, and use the "ReplaceFirst" method from this question to loop over the string, replacing each occurrence of ? with the appropriate #P#.\
How do I replace the *first instance* of a string in .NET?
Maybe something like this:
int i = 0;
while (myString.Contains("?"))
{
myString = myString.ReplaceFirst("?", "#P" + i);
i++;
}
Note that "ReplaceFirst" is not a standard method on string - you have to implement it (e.g. as an extension method, in this example).
Why not generate your SQL as you get your parameters defining proper CASE in your code and give it to execution at the very end when it is ready?
If you want something out of the box :)
string toFormat = "?, ? ,? AND BOB";
while (toFormat.Contains(" "))
toFormat = toFormat.Replace(" ", " ");
toFormat = toFormat.Replace("?", "{0}");
string formated = string.Format(toFormat, new PCounter());
Where PCounter is like this
class PCounter{
int i = 0;
public override string ToString(){
return "#P" + (++i);
}
}
I think something like the below should do it.
string input = "BOB AND ?,?,?,?,?";
int number = 1;
int index = input.IndexOf("?");
while (index > -1)
{
input = input.Substring(0, index).Trim() + " #P" + number++.ToString() + input.Substring(index + 1).Trim();
index = input.IndexOf("?");
}
I have a string User name (sales) and I want to extract the text between the brackets, how would I do this?
I suspect sub-string but I can't work out how to read until the closing bracket, the length of text will vary.
If you wish to stay away from regular expressions, the simplest way I can think of is:
string input = "User name (sales)";
string output = input.Split('(', ')')[1];
A very simple way to do it is by using regular expressions:
Regex.Match("User name (sales)", #"\(([^)]*)\)").Groups[1].Value
As a response to the (very funny) comment, here's the same Regex with some explanation:
\( # Escaped parenthesis, means "starts with a '(' character"
( # Parentheses in a regex mean "put (capture) the stuff
# in between into the Groups array"
[^)] # Any character that is not a ')' character
* # Zero or more occurrences of the aforementioned "non ')' char"
) # Close the capturing group
\) # "Ends with a ')' character"
Assuming that you only have one pair of parenthesis.
string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);
Use this function:
public string GetSubstringByString(string a, string b, string c)
{
return c.Substring((c.IndexOf(a) + a.Length), (c.IndexOf(b) - c.IndexOf(a) - a.Length));
}
and here is the usage:
GetSubstringByString("(", ")", "User name (sales)")
and the output would be:
sales
Regular expressions might be the best tool here. If you are not famililar with them, I recommend you install Expresso - a great little regex tool.
Something like:
Regex regex = new Regex("\\((?<TextInsideBrackets>\\w+)\\)");
string incomingValue = "Username (sales)";
string insideBrackets = null;
Match match = regex.Match(incomingValue);
if(match.Success)
{
insideBrackets = match.Groups["TextInsideBrackets"].Value;
}
string input = "User name (sales)";
string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);
A regex maybe? I think this would work...
\(([a-z]+?)\)
using System;
using System.Text.RegularExpressions;
private IEnumerable<string> GetSubStrings(string input, string start, string end)
{
Regex r = new Regex(Regex.Escape(start) +`"(.*?)"` + Regex.Escape(end));
MatchCollection matches = r.Matches(input);
foreach (Match match in matches)
yield return match.Groups[1].Value;
}
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);
Use a Regular Expression:
string test = "(test)";
string word = Regex.Match(test, #"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);
The regex method is superior I think, but if you wanted to use the humble substring
string input= "my name is (Jayne C)";
int start = input.IndexOf("(");
int stop = input.IndexOf(")");
string output = input.Substring(start+1, stop - start - 1);
or
string input = "my name is (Jayne C)";
string output = input.Substring(input.IndexOf("(") +1, input.IndexOf(")")- input.IndexOf("(")- 1);
var input = "12(34)1(12)(14)234";
var output = "";
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '(')
{
var start = i + 1;
var end = input.IndexOf(')', i + 1);
output += input.Substring(start, end - start) + ",";
}
}
if (output.Length > 0) // remove last comma
output = output.Remove(output.Length - 1);
output : "34,12,14"
Here is a general purpose readable function that avoids using regex:
// Returns the text between 'start' and 'end'.
string ExtractBetween(string text, string start, string end)
{
int iStart = text.IndexOf(start);
iStart = (iStart == -1) ? 0 : iStart + start.Length;
int iEnd = text.LastIndexOf(end);
if(iEnd == -1)
{
iEnd = text.Length;
}
int len = iEnd - iStart;
return text.Substring(iStart, len);
}
To call it in your particular example you can do:
string result = ExtractBetween("User name (sales)", "(", ")");
I'm finding that regular expressions are extremely useful but very difficult to write. So, I did some research and found this tool that makes writing them so easy.
Don't shy away from them because the syntax is difficult to figure out. They can be so powerful.
This code is faster than most solutions here (if not all), packed as String extension method, it does not support recursive nesting:
public static string GetNestedString(this string str, char start, char end)
{
int s = -1;
int i = -1;
while (++i < str.Length)
if (str[i] == start)
{
s = i;
break;
}
int e = -1;
while(++i < str.Length)
if (str[i] == end)
{
e = i;
break;
}
if (e > s)
return str.Substring(s + 1, e - s - 1);
return null;
}
This one is little longer and slower, but it handles recursive nesting more nicely:
public static string GetNestedString(this string str, char start, char end)
{
int s = -1;
int i = -1;
while (++i < str.Length)
if (str[i] == start)
{
s = i;
break;
}
int e = -1;
int depth = 0;
while (++i < str.Length)
if (str[i] == end)
{
e = i;
if (depth == 0)
break;
else
--depth;
}
else if (str[i] == start)
++depth;
if (e > s)
return str.Substring(s + 1, e - s - 1);
return null;
}
I've been using and abusing C#9 recently and I can't help throwing in Spans even in questionable scenarios... Just for the fun of it, here's a variation on the answers above:
var input = "User name (sales)";
var txtSpan = input.AsSpan();
var startPoint = txtSpan.IndexOf('(') + 1;
var length = txtSpan.LastIndexOf(')') - startPoint;
var output = txtSpan.Slice(startPoint, length);
For the OP's specific scenario, it produces the right output.
(Personally, I'd use RegEx, as posted by others. It's easier to get around the more tricky scenarios where the solution above falls apart).
A better version (as extension method) I made for my own project:
//Note: This only captures the first occurrence, but
//can be easily modified to scan across the text (I'd prefer Slicing a Span)
public static string ExtractFromBetweenChars(this string txt, char openChar, char closeChar)
{
ReadOnlySpan<char> span = txt.AsSpan();
int firstCharPos = span.IndexOf(openChar);
int lastCharPos = -1;
if (firstCharPos != -1)
{
for (int n = firstCharPos + 1; n < span.Length; n++)
{
if (span[n] == openChar) firstCharPos = n; //This allows the opening char position to change
if (span[n] == closeChar) lastCharPos = n;
if (lastCharPos > firstCharPos) break;
//This would correctly extract "sales" from this [contrived]
//example: "just (a (name (sales) )))(test"
}
return span.Slice(firstCharPos + 1, lastCharPos - firstCharPos - 1).ToString();
}
return "";
}
Much similar to #Gustavo Baiocchi Costa but offset is being calculated with another intermediate Substring.
int innerTextStart = input.IndexOf("(") + 1;
int innerTextLength = input.Substring(start).IndexOf(")");
string output = input.Substring(innerTextStart, innerTextLength);
I came across this while I was looking for a solution to a very similar implementation.
Here is a snippet from my actual code. Starts substring from the first char (index 0).
string separator = "\n"; //line terminator
string output;
string input= "HowAreYou?\nLets go there!";
output = input.Substring(0, input.IndexOf(separator));