remove url from a given string in c# - c#

I tried doing this
using System;
using System.Collections.Generic;
using System.Text;
namespace UrlsDetector
{
class UrlDetector
{
public static string RemoveUrl(string input)
{
var words = input;
while(words.Contains("https://"))
{
string urlToRemove = words.Substring("https://", #" ");
words = words.Replace("https://" + urlToRemove , #"");
}
}
}
class Program
{
static void Main()
{
Console.WriteLine(UrlDetector.RemoveUrl(
"I saw a cat and a horse on https://www.youtube.com/"));
}
}
}
but it doesn't work
what I want to achieve is remove the entire "https://www.youtube.com/" and display "I saw a cat and a horse on"
I also want to display a message like "the sentence you input doesn't have url" if the sentence doesn't have any url. but as you can I didnt put any code to do that I just need to fix this code first but if you want to help me do that too, I gladly appreciated it.
thanks for responses.

If you are looking for a non RegEx way to do this, here you go. But the method I encoded below assumes that a URL begins with "http://" or "https://", which means it will not work with URL's that begin with something like ftp:// or file://, although the code below can be easily modified to support that. Also, it assumes the URL path continues until it reaches either the end of the string or a white space character (like a space or a tab or a new line). Again, this can easily be modified if your requirements are different.
Also, if the string contains no URL, currently it just returns a blank string. You can modify this easily too!
using System;
public class Program
{
public static void Main()
{
string str = "I saw a cat and a horse on https://www.youtube.com/";
UrlExtraction extraction = RemoveUrl(str);
Console.WriteLine("Original Text: " + extraction.OriginalText);
Console.WriteLine();
Console.WriteLine("Url: " + extraction.ExtractedUrl);
Console.WriteLine("Text: " + extraction.TextWithoutUrl);
}
private static UrlExtraction RemoveUrl(string str)
{
if (String.IsNullOrWhiteSpace(str))
{
return new UrlExtraction("", "", "");
}
int startIndex = str.IndexOf("https://",
StringComparison.InvariantCultureIgnoreCase);
if (startIndex == -1)
{
startIndex = str.IndexOf("http://",
StringComparison.InvariantCultureIgnoreCase);
}
if (startIndex == -1)
{
return new UrlExtraction(str, "", "");
}
int endIndex = startIndex;
while (endIndex < str.Length && !IsWhiteSpace(str[endIndex]))
{
endIndex++;
}
return new UrlExtraction(str, str.Substring(startIndex, endIndex - startIndex),
str.Remove(startIndex, endIndex - startIndex));
}
private static bool IsWhiteSpace(char c)
{
return
c == '\n' ||
c == '\r' ||
c == ' ' ||
c == '\t';
}
private class UrlExtraction
{
public string ExtractedUrl {get; set;}
public string TextWithoutUrl {get; set;}
public string OriginalText {get; set;}
public UrlExtraction(string originalText, string extractedUrl,
string textWithoutUrl)
{
OriginalText = originalText;
ExtractedUrl = extractedUrl;
TextWithoutUrl = textWithoutUrl;
}
}
}

A simplified version of what you're doing. Instead of using SubString or IndexOf, I split the input into a list of strings, and remove the items that contain a URL. I iterate over the list in reverse as removing an item in a forward loop direction will skip an index.
public static string RemoveUrl(string input)
{
List<string> words = input.Split(" ").ToList();
for (int i = words.Count - 1; i >= 0; i--)
{
if (words[i].StartsWith("https://")) words.RemoveAt(i);
}
return string.Join(" ", words);
}
This methods advantage is avoiding SubString and Replace methods that essentially create new Strings each time they're used. In a loop this excessive string manipulation can put pressure on the Garbage Collector and bloat the Managed Heap. A Split and Join has less performance cost in comparison especially when used in a loop like this with a lot of data.
#Moshi is correct with large amounts of data, so this is more of a Production Code Base example:
public static class Ext
{
public static LinkedList<T> RemoveAll<T>(this LinkedList<T> list, Predicate<T> match)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
if (match == null)
{
throw new ArgumentNullException("match");
}
var count = 0;
var node = list.First;
while (node != null)
{
var next = node.Next;
if (match(node.Value))
{
list.Remove(node);
count++;
}
node = next;
}
return list;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var s= "I saw a https://www.youtube.com/cat and a https://www.youtube.com/horse on https://www.youtube.com/";
//Uncomment for second run
//s= #"I saw a https://www.youtube.com/cat and a https://www.youtube.com/horse on https://www.youtube.com/
//but it doesnt work
//what I want to achieve is remove the entire https://www.youtube.com/ and display I saw a cat and a horse on
//I also want to display a message like the sentence you input doesn't have url if the sentence doesn't have any url. but as you can I didnt put any code to do that I just need to fix this code first but if you want to help me do that too, I gladly appreciated it.
//thanks for responses.";
Stopwatch watch = new Stopwatch();
watch.Start();
var resultList = RemoveUrl(s);
watch.Stop(); Debug.WriteLine(watch.Elapsed.ToString());
watch.Reset(); watch.Start();
var wordsLL = new LinkedList<string>(s.Split(' '));
var result = string.Join(' ', wordsLL.RemoveAll(x => x.StartsWith("https://")));
watch.Stop(); Debug.WriteLine(watch.Elapsed.ToString());
}
}
var s one line:
watch.Elapsed = {00:00:00.0116388}
watch.Elapsed = {00:00:00.0134778}
var s multilines:
watch.Elapsed = {00:00:00.0013588}
watch.Elapsed = {00:00:00.0009252}

Using basic string manipulation will never get you where you want to be.
Using regular expressions makes this very easy for you.
search for a piece of text that looks like
"http(s)?:\/\/\S*[^\s\.]":
http: the text block http
(s)?: the optional (?) letter s
:\/\/: the characters ://
\S*: any amount (*) non white characters (\S)
[^\s\.]: any character that is not (^) in the list ([ ]) of characters being white characters (\s) or dot (\.). This allows you to exclude the dot at the end of a sentence from your url.
using System;
using System.Text.RegularExpressions;
namespace UrlsDetector
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine(UrlDetector.RemoveUrl(
"I saw a cat and a horse on https://www.youtube.com/ and also on http://www.example.com."));
Console.ReadLine();
}
}
class UrlDetector
{
public static string RemoveUrl(string input)
{
var regex = new Regex($#"http(s)?:\/\/\S*[^\s.]");
return regex.Replace(input, "");
}
}
}
Using regular expressions you can also detect matches Regex.Match(...) which allows you to detect any urls in your text.

Better way to use, split and StringBuilder. Code will be look like this. StringBuilder is optimized this kind of situation.
Pseudocode:
var words = "I saw a cat and a horse on https://www.youtube.com/".Split(" ").ToList();
var sb = new StringBuilder();
foreach(var word in words){
if(!word.StartsWith("https://")) sb.Append(word + " ");
}
return sb.ToString();

Related

Method that takes a message and index, creates a substring using the index

Problem: I want to write a method that takes a message/index pair like this:
("Hello, I am *Name1, how are you doing *Name2?", 2)
The index refers to the asterisk delimited name in the message. So if the index is 1, it should refer to *Name1, if it's 2 it should refer to *Name2.
The method should return just the name with the asterisk (*Name2).
I have attempted to play around with substrings, taking the first delimited * and ending when we reach a character that isn't a letter, number, underscore or hyphen, but the logic just isn't setting in.
I know this is similar to a few problems on SO but I can't find anything this specific. Any help is appreciated.
This is what's left of my very vague attempt so far. Based on this thread:
public string GetIndexedNames(string message, int index)
{
int strStart = message.IndexOf("#") + "#".Length;
int strEnd = message.LastIndexOf(" ");
String result = message.Substring(strStart, strEnd - strStart);
}
If you want to do it the old school way, then something like:
public static void Main(string[] args)
{
string message = "Hello, I am *Name1, how are you doing *Name2?";
string name1 = GetIndexedNames(message, "*", 1);
string name2 = GetIndexedNames(message, "*", 2);
Console.WriteLine(message);
Console.WriteLine(name1);
Console.WriteLine(name2);
Console.ReadLine();
}
public static string GetIndexedNames(string message, string singleCharDelimiter, int index)
{
string valid = "abcdefghijlmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
string[] parts = message.Split(singleCharDelimiter.ToArray());
if (parts.Length >= index)
{
StringBuilder sb = new StringBuilder();
for(int i = 0; i < parts[index].Length; i++)
{
string character = parts[index].Substring(i, 1);
if (valid.Contains(character))
{
sb.Append(character);
}
else
{
return sb.ToString();
}
}
return sb.ToString();
}
return "";
}
You can try using regular expressions to match the names. Assuming that name is a sequence of word characters (letters or digits):
using System.Linq;
using System.Text.RegularExpressions;
...
// Either name with asterisk *Name or null
// index is 1-based
private static ObtainName(string source, int index) => Regex
.Matches(source, #"\*\w+")
.Cast<Match>()
.Select(match => match.Value)
.Distinct() // in case the same name repeats several times
.ElementAtOrDefault(index - 1);
Demo:
string name = ObtainName(
"Hello, I am *Name1, how are you doing *Name2?", 2);
Console.Write(name);
Outcome:
*Name2
Perhaps not the most elegant solution, but if you want to use IndexOf, use a loop:
public static string GetIndexedNames(string message, int index, char marker='*')
{
int lastFound = 0;
for (int i = 0; i < index; i++) {
lastFound = message.IndexOf(marker, lastFound+1);
if (lastFound == -1) return null;
}
var space = message.IndexOf(' ', lastFound);
return space == -1 ? message.Substring(lastFound) : message.Substring(lastFound, space - lastFound);
}

After instruction still can not make for loop with C# [duplicate]

This question already has answers here:
How do I create a terminable while loop in console application?
(7 answers)
Closed 3 years ago.
I started a C# course now and there is an assignment where I have to create a "palindrome detector" program. Point is that user inputs some word or sentence, then I have to remove chars like ,.;:!? and space from it. I have done that with two different methods, because char method can not remove space so I wrote another method for it.
After "cleaning" operation program reversing input what user gave, and comparing original user input and reversed user input to each other. It they are same it prints "It is palindrome", if they are different it prints "It is not palindrome". That is working fine, BUT THE PROBLEM IS I have to put them in for loop. It have to ask input again and again, until user give empty.
This would be very easy, but somehow I can not do it.
Here is my code:
using System;
namespace Palindromi
{
class Program
{
static void Main()
{
Console.WriteLine("Hei! Tervetuloa palindromin tunnistusohjelmaan. Tämä tunnistaa, onko syöttämäsi sana sama toisinpäin!");
Console.Write("Anna teksti (tyhjä lopettaa): ");
string userinput = Console.ReadLine(); //userinput is user's input, this is what you have to modify. remove some chars and reverse it.
if (userinput == "")
{
Console.ReadLine();//when i have loop this have to be "break". This meant to break for loop when i have it.
}
char[] removechars = { '.', ':', ';', ',', '!', '?' };//this is the list of "have to be removed" chars
string userinput_without_chars = userinput.Trim(removechars); //this method remove chars which are listed
string userinput_without_chars_space = userinput_without_chars.Replace( " ", ""); //replace space with empty
string reverse_string, reversed;
reverse_string = userinput_without_chars_space;
reversed = "";
int len;
len = userinput_without_chars_space.Length - 1;
while (len >= 0)
{
reversed = reversed + reverse_string[len];
len--;
}
Console.WriteLine("Sana käännettynä on {0}", reversed); //tells user input reversed
if (userinput_without_chars_space == reversed)//check is the userinput same than reversed user input
{
Console.Write("On palindromi.");//it is palindrome
}
else
{
Console.Write("Ei ole palindromi.");//it is not palindrome
}
}
}
}
You could potentially do something along these lines:
var running = true;
while(running)
{
var input = Console.ReadLine().ToLower();
var phrase = input.Sanitize(new List<string>() {".", ",", "?", "!", "'", "&", "%", "$", " "});
if(phrase.IsPalindrome())
Console.Writeline("Input was palindrome.");
}
public static string Sanitize(this string input, IList<string> punctuation) =>
String.Join(String.Empty, input.Where(character => punctuation.Contains(character) == false));
public static bool IsPalindrome(this string sentence)
{
for (int l = 0, r = sentence.Length - 1; l < r; l++, r--)
if (sentence[l] != sentence[r])
return false;
return true;
}
public static void Close(string input)
{
// Some logic to see if the application should stop.
}
You could create another method that looks for commands, or keystrokes, then sets the boolean to run as false. Which would break the infinite loop. You could also do an abrupt close with Environment.Exit.
The very simplest approach is replace your Console.ReadLine() where you want to break to return.
Alternatively, you could wrap the logic in another while loop.
while (userinput != "")
{
// Remove chars
// rest of your logic
/* IMPORTANT */
userinput = Console.Readline();
}
To remove the symbols from the input, you can use the Regex.Replace method. In this case, you can be sure, that the specified symbols will be correctly removed from the input string. Note, that you can handle the whitespaces along with other characters you mentioned, like in the code snippet below:
var CharactersToRemove { get; set; } = " ,.;:!?";
var processedInput = Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
Note, that here I used input.ToLower() to convert the input to a lowercase string. This will make the palindrome tests case-insensitive. Should you need case-sensitive palindrome tests, just remove the .ToLower() part.
There is no need to reverse the input string to check if it is a palindrome. You can check this within one for loop as follows:
bool CheckForBeingaAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
Note, that in this case you only iterate over the elements of the input string once. This approach will give you al least 4 times better performance than the one you used.
Below, you can find a complete minimal working solution to your problem.
using System.Text.RegularExpressions;
using static System.Console;
namespace Assignment
{
public static class PalindromeFinder
{
public static string CharactersToRemove { get; set; } = " ,.;:!?";
public static bool IsPalindrome(string input)
{
var processedInput = RemoveUnnecessaryCharacters(input);
return CheckForBeingAPalindrome(processedInput);
}
private static string RemoveUnnecessaryCharacters(string input)
{
return Regex.Replace(input.ToLower(), $"[{CharactersToRemove}]", string.Empty);
}
private static bool CheckForBeingAPalindrome(string input)
{
var frontIndex = 0;
var tailIndex = input.Length - 1;
for (; frontIndex < tailIndex;)
{
if (input[frontIndex] != input[tailIndex])
return false;
++frontIndex;
--tailIndex;
}
return true;
}
}
public class Program
{
private static void Main(string[] args)
{
ContinuouslyCheckUserInputForBeingAPalindrome();
}
private static void ContinuouslyCheckUserInputForBeingAPalindrome()
{
while (FetchUserInputFromConsole() is string input
&& !string.IsNullOrWhiteSpace(input))
{
var isPalindrome = PalindromeFinder.IsPalindrome(input);
var modifier = isPalindrome ? "a" : "not a";
WriteLine($"It is {modifier} palindrome");
}
}
private static string FetchUserInputFromConsole()
{
Write("Enter a string: ");
return ReadLine();
}
}
}

List all of the "A"'s in string

I wanted to count all of the "A's" in a paritcular string.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace TESTING
{
class Testing
{
static void Main(string[] args)
{
//ask user for the filename
string userInput = fetchFileName("Enter the textfile you want to view: ");
//test if the filename writes anything to console
string fileContents = File.ReadAllText(userInput);
string theFileContents = analyseFile(fileContents);
// Console.WriteLine(theFileContents);
Console.ReadLine();
}
private static string analyseFile(string fileContents)
{
string str = fileContents;
if (str.Contains("A"))
{
Console.WriteLine("YES");
}
else
{
Console.WriteLine("NO");
}
return str;
}
private static string fetchFileName(string askFileName)
{
Console.WriteLine(askFileName);
string userAnswer = Console.ReadLine();
return userAnswer;
}
}
}
Take a look at LINQ. It allows to perform whole range of operations on any kind of collection. And a string is a collection of chars. Below an example how LINQ can make your life easier:
string text = "A sdfsf a A sdfsf AAS sdfA";
int res = text.Count(letter => letter == 'A');
What happens here is that you take text and provide a predicat saying that you want to take any variable letter from the string such that the letter is equal to char A. Then you want to count them.
One of the easiest ways is to iterate over all characters in your file and check if the letter is equal to the letter you want.
When you realize that a string is nothing more then an array of characters, you can do something like this:
public int LetterCount(string filename, char letter)
{
int cnt = 0;
string source = File.ReadAllText(filename);
//Check every character in your string; if it matches increase the counter by 1
foreach (char c in source)
{
if(c == letter)
{
cnt++;
}
}
return cnt;
}
And use it like this:
int A_count = LetterCount(#"C:\test.txt", 'A');
Please note, that this code does not check, if the file actually exists. If you put in a wrong path, you end up with a FileNotFoundException.
Foreach is just another type of loop. This could just as easily be done with a for-loop. The trick is to split the string up in individual characters that you can later compare.
I'm sure you will figure out how to implement this if I just set you on the right path:
string test = "My name is Isak";
char[] arrayOfChars = test.ToCharArray();
int count = 0;
for (int i = 0; i < arrayOfChars.Length; i++)
{
if (arrayOfChars[i] == 'a' || arrayOfChars[i] == 'A')
{
count++;
}
}
try simple as
string test = "ABBCDABNDEAA";
int Count = test.Count(x => x == 'A');
Using LINQ, this can by really simple:
string myString = "ababsgsdfsaaaAA22bbaa";
var count = myString.ToLower().Count(c => c == 'a');
Console.Write(count);
Here we take the string and convert it to all lower case so that A and a will be counted together. Then we use the simple LINQ method Count() to count the number of a characters there are.
You could use linq
string text = "The quick brown fox jumps over the lazy dog";
var count = text.ToLower().Where(x => x == 'a').Count();
Console.WriteLine(count);
But if you cannot use any advanced techniques you could do it like this:
string text = "The quick brown fox jumps over the lazy dog";
int counter = 0;
for (int i = 0; i < text.Count(); i++)
{
if (text[i] == 'a' || text[i] == 'A')
{
counter++;
}
}
Console.WriteLine(counter);
You can do this:
string stringValue = "Addsadsd AAf,,werAA";
int qtdChar = stringValue.Count(x => x == 'A');
int qtdCharInsensitive = stringValue.Count(x => x == 'A' || x=='a');
If you do not want to use a foreach you could erase all the letter A's and compare the length difference.
A bit like this :
private static string analyseFile(string fileContents)
{
var strippedString = fileContents.Replace("A","");
var count = fileContents.Length - strippedString.Length;
return count.ToString();
}

How can I search through a string in C# and replace areas bounded by a pattern?

We tried a few solutions now that try and use XML parsers. All fail because the strings are not always 100% valid XML. Here's our problem.
We have strings that look like this:
var a = "this is a testxxx of my data yxxx and of these xxx parts yxxx";
var b = "hello testxxx world yxxx ";
"this is a testxxx3yxxx and of these xxx1yxxx";
"hello testxxx1yxxx ";
The key here is that we want to do something to the data between xxx and yxxx. In the example above I would need a function that counts words and replaces the strings with a word count.
Is there a way we can process the string a and apply a function to change the data that's between the xxx and yxxx? Any function right now as we're just trying to get an idea of how to code this.
You can use Split method:
var parts = a.Split(new[] {"xxx", "yxxx"}, StringSplitOptions.None)
.Select((s, index) =>
{
string s1 = index%2 == 1 ? string.Format("{0}{2}{1}", "xxx", "yxxx", s + "1") : s;
return s1;
});
var result = string.Join("", parts);
If it always going to xxx and yxxx, you can use regex as suggested.
var stringBuilder = new StringBuilder();
Regex regex = new Regex("xxx(.*?)yxxx");
var splitGroups = Regex.Match(a);
foreach(var group in splitGroups)
{
var value = splitGroupsCopy[i];
// do something to value and then append it to string builder
stringBuilder.Append(string.Format("{0}{1}{2}", "xxx", value, "yxxx"));
}
I suppose this is as basic as it gets.
Using Regex.Replace will replace all the matches with your choice of text, something like this:
Regex rgx = new Regex("xxx.+yxxx");
string cleaned = rgx.Replace(a, "replacementtext");
This code will process each of the parts delimited by "xxx". It preserves the "xxx" separators. If you do not want to preserve the "xxx" separators, remove the two lines that say "result.Append(separator);".
Given:
"this is a testxxx of my data yxxx and there are many of these xxx parts yxxx"
It prints:
"this is a testxxx>> of my data y<<xxx and there are many of these xxx>> parts y<<xxx"
I'm assuming that's the kind of thing you want. Add your own processing to "processPart()".
using System;
using System.Text;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
string text = "this is a testxxx of my data yxxx and there are many of these xxx parts yxxx";
string separator = "xxx";
var result = new StringBuilder();
int index = 0;
while (true)
{
int start = text.IndexOf(separator, index);
if (start < 0)
{
result.Append(text.Substring(index));
break;
}
result.Append(text.Substring(index, start - index));
int end = text.IndexOf(separator, start + separator.Length);
if (end < 0)
{
throw new InvalidOperationException("Unbalanced separators.");
}
start += separator.Length;
result.Append(separator);
result.Append(processPart(text.Substring(start, end-start)));
result.Append(separator);
index = end + separator.Length;
}
Console.WriteLine(result);
}
private static string processPart(string part)
{
return ">>" + part + "<<";
}
}
}
[EDIT] Here's the code amended to work with two different separators:
using System;
using System.Text;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
string text = "this is a test<pre> of my data y</pre> and there are many of these <pre> parts y</pre>";
string separator1 = "<pre>";
string separator2 = "</pre>";
var result = new StringBuilder();
int index = 0;
while (true)
{
int start = text.IndexOf(separator1, index);
if (start < 0)
{
result.Append(text.Substring(index));
break;
}
result.Append(text.Substring(index, start - index));
int end = text.IndexOf(separator2, start + separator1.Length);
if (end < 0)
{
throw new InvalidOperationException("Unbalanced separators.");
}
start += separator1.Length;
result.Append(separator1);
result.Append(processPart(text.Substring(start, end-start)));
result.Append(separator2);
index = end + separator2.Length;
}
Console.WriteLine(result);
}
private static string processPart(string part)
{
return "|" + part + "|";
}
}
}
The indexOf() function will return to you the index of the first occurrence of a given substring.
(My indices might be a bit off, but) I would suggest doing something like this:
var searchme = "this is a testxxx of my data yxxx and there are many of these xxx parts yxxx";
var startindex= searchme.indexOf("xxx");
var endindex = searchme.indexOf("yxxx") + 3; //added 3 to find the index of the last 'x' instead of the index of the 'y' character
var stringpiece = searchme.substring(startindex, endindex - startindex);
and you can repeat that while startindex != -1
Like I said, the indices might be slightly off, you might have to add a +1 or -1 somewhere, but this will get you along nicely (I think).
Here is a little sample program that counts chars instead of words. But you should just need to change the processor function.
var a = "this is a testxxx of my data yxxx and there are many of these xxx parts yxxx";
a = ProcessString(a, CountChars);
string CountChars(string a)
{
return a.Length.ToString();
}
string ProcessString(string a, Func<string, string> processor)
{
int idx_start, idx_end = -4;
while ((idx_start = a.IndexOf("xxx", idx_end + 4)) >= 0)
{
idx_end = a.IndexOf("yxxx", idx_start + 3);
if (idx_end < 0)
break;
var string_in_between = a.Substring(idx_start + 3, idx_end - idx_start - 3);
var newString = processor(string_in_between);
a = a.Substring(0, idx_start + 3) + newString + a.Substring(idx_end, a.Length - idx_end);
idx_end -= string_in_between.Length - newString.Length;
}
return a;
}
I would use Regex Groups:
Here my solution to get the parts in the string:
private static IEnumerable<string> GetParts( string searchFor, string begin, string end ) {
string exp = string.Format("({0}(?<searchedPart>.+?){1})+", begin, end);
Regex regex = new Regex(exp);
MatchCollection matchCollection = regex.Matches(searchFor);
foreach (Match match in matchCollection) {
Group #group = match.Groups["searchedPart"];
yield return #group.ToString();
}
}
you can use it like to get the parts:
string a = "this is a testxxx of my data yxxx and there are many of these xxx parts yxxx";
IEnumerable<string> parts = GetParts(a, "xxx", "yxxx");
To replace the parts in the original String you can use the Regex Group to determine Length and StartPosition (#group.Index, #group.Length).

C# fix sentence

I need to take a sentence in that is all on one line with no spaces and each new word has a captial letter EX. "StopAndSmellTheRoses" and then convert it to "Stop and smell the roses" This is my function that I have but I keep getting an argument out of range error on the insert method. Thanks for any help in advance.
private void FixSentence()
{
// String to hold our sentence in trim at same time
string sentence = txtSentence.Text.Trim();
// loop through the string
for (int i = 0; i < sentence.Length; i++)
{
if (char.IsUpper(sentence, i) & sentence[i] != 0)
{
// Change to lowercase
char.ToLower(sentence[i]);
// Insert space behind the character
// This is where I get my error
sentence = sentence.Insert(i-1, " ");
}
}
// Show our Fixed Sentence
lblFixed.Text = "";
lblFixed.Text = "Fixed: " + sentence;
}
The best way to build up a String in this manner is to use a StringBuilder instance.
var sentence = txtSentence.Text.Trim();
var builder = new StringBuilder();
foreach (var cur in sentence) {
if (Char.IsUpper(cur) && builder.Length != 0) {
builder.Append(' ');
}
builder.Append(cur);
}
// Show our Fixed Sentence
lblFixed.Text = "";
lblFixed.Text = "Fixed: " + builder.ToString();
Using the Insert method creates a new string instance every time resulting in a lot of needlessly allocated values. The StringBuilder though won't actually allocate a String until you call the ToString method.
You can't modify the sentence variable in the loop that is going through it.
Instead, you need to have a second string variable that you append all of the found words.
Here is the answer
var finalstr = Regex.Replace(
"StopAndSmellTheRoses",
"(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])|(?<=[^0-9])(?<x>[0-9])(?=.)",
me => " " + me.Value.ToLower()
);
will output
Stop and smell the roses
Another version:
public static class StringExtensions
{
public static string FixSentence(this string instance)
{
char[] capitals = Enumerable.Range(65, 26).Select(x => (char)x).ToArray();
string[] words = instance.Split(capitals);
string result = string.Join(' ', words);
return char.ToUpper(result[0]) + result.Substring(1).ToLower();
}
}

Categories

Resources