Replace the first occurrence in a string - c#

I have this string :
Hello my name is Marco
and I'd like to replace the first space (between Hello and my) with <br />. Only the first.
What's the best way to do it on C#/.NET 3.5?

public static class MyExtensions
{
public static string ReplaceFirstOccurrance(this string original, string oldValue, string newValue)
{
if (String.IsNullOrEmpty(original))
return String.Empty;
if (String.IsNullOrEmpty(oldValue))
return original;
if (String.IsNullOrEmpty(newValue))
newValue = String.Empty;
int loc = original.IndexOf(oldValue);
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);
}
}
and use it like:
string str="Hello my name is Marco";
str.ReplaceFirstOccurrance("Hello", "<br/>");
str.ReplaceFirstOccurrance("my", "<br/>");

No need to add substrings, following will find the first space instance only.
From MSDN:
Reports the zero-based index of the first occurrence of the specified
string in this instance.
string x = "Hello my name is Marco";
int index = x.IndexOf(" ");
if (index >= 0)
{
x=x.Remove(index,1);
x = x.Insert(index, #"<br />");
}
Edit: If you are not sure if space will occur, some validations must come into place. I have edit the answer accordingly.

string tmp = "Hello my name is Marco";
int index = tmp.IndexOf(" ");
tmp = tmp.Substring(0, index) + "<br />" + tmp.Substring(index + 1);

Here you go, this would work:
var s = "Hello my name is Marco";
var firstSpace = s.IndexOf(" ");
var replaced = s.Substring(0,firstSpace) + "<br/>" + s.Substring(firstSpace+1);
You could make this into an extension method:
public static string ReplaceFirst(this string input, string find, string replace){
var first= s.IndexOf(find);
return s.Substring(0,first) + replace + s.Substring(first+find.Length);
}
And then the usage would be
var s = "Hello my name is Marco";
var replaced = s.ReplaceFirst(" ","<br/>");

string[] str = "Hello my name is Marco".Split(' ');
string newstr = str[0] + "<br /> " + string.Join(" ", str.Skip(1).ToArray());

Simply use
Replace("Hello my name is Marco", " ", "<br />", 1, 1)

Related

get values from array and add into one string

Object Book has Author which has property Name of type string.
I want to iterate trough all Authors and add it's Name string to the one string (not array) separated by comma, so this string should be at the as
string authorNames = "Author One, Author two, Author three";
string authorNames = string.Empty;
foreach(string item in book.Authors)
{
string fetch = item.Name;
??
}
You can use the string.Join function with LINQ
string authorNames = string.Join(", ", book.Authors.Select(a => a.Name));
You can use
string authors = String.Join(", ", book.Authors.Select(a => a.Name));
LINQ is the way to go in C#, but for explanatory purposes here is how you could code it explicitly:
string authorNames = string.Empty;
for(int i = 0; i < book.Authors.Count(); i++)
{
if(i > 0)
authorNames += ", ";
authorNames += book.Authors[i].Name;
}
You could also loop through them all, and append them to authorNames and add a comma in the end, and when it's done simply trim of the last comma.
string authorNames = string.Empty;
foreach(string author in book.Authors)
{
string authorNames += author.Name + ", ";
}
authorNames.TrimEnd(',');
Using LinQ, there are plenty of ways to merge multiple string into one string.
book.Authors.Select(x => x.Name).Aggregate((x, y) => x + ", " + y);
To anwsers James' comment
[TestMethod]
public void JoinStringsViaAggregate()
{
var mystrings = new[] {"Alpha", "Beta", "Gamma"};
var result = mystrings.Aggregate((x, y) => x + ", " + y);
Assert.AreEqual("Alpha, Beta, Gamma", result);
}

Get String (Text) before next upper letter

I have the following:
string test = "CustomerNumber";
or
string test2 = "CustomerNumberHello";
the result should be:
string result = "Customer";
The first word from the string is the result, the first word goes until the first uppercase letter, here 'N'
I already tried some things like this:
var result = string.Concat(s.Select(c => char.IsUpper(c) ? " " + c.ToString() : c.ToString()))
.TrimStart();
But without success, hope someone could offer me a small and clean solution (without RegEx).
The following should work:
var result = new string(
test.TakeWhile((c, index) => index == 0 || char.IsLower(c)).ToArray());
You could just go through the string to see which values (ASCII) are below 97 and remove the end. Not the prettiest or LINQiest way, but it works...
string test2 = "CustomerNumberHello";
for (int i = 1; i < test2.Length; i++)
{
if (test2[i] < 97)
{
test2 = test2.Remove(i, test2.Length - i);
break;
}
}
Console.WriteLine(test2); // Prints Customer
Try this
private static string GetFirstWord(string source)
{
return source.Substring(0, source.IndexOfAny("ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray(), 1));
}
Z][a-z]+ regex it will split the string to string that start with big letters her is an example
regex = "[A-Z][a-z]+";
MatchCollection mc = Regex.Matches(richTextBox1.Text, regex);
foreach (Match match in mc)
if (!match.ToString().Equals(""))
Console.writln(match.ToString() + "\n");
I have tested, this works:
string cust = "CustomerNumberHello";
string[] str = System.Text.RegularExpressions.Regex.Split(cust, #"[a-z]+");
string str2 = cust.Remove(cust.IndexOf(str[1], 1));

How to mask string?

I have a string with value "1131200001103".
How can I display it as a string in this format "11-312-001103" using Response.Write(value)?
Thanks
This produces the required result
string result = Int64.Parse(s.Remove(5,2)).ToString("00-000-000000");
assuming that you want to drop 2 characters at the position of the 2 first nulls.
Any reason you don't want to just use Substring?
string dashed = text.Substring(0, 2) + "-" +
text.Substring(2, 3) + "-" +
text.Substring(7);
Or:
string dashed = string.Format("{0}-{1}-{2}", text.Substring(0, 2),
text.Substring(2, 3), text.Substring(7));
(I'm assuming it's deliberate that you've missed out two of the 0s? It's not clear which 0s, admittedly...)
Obviously you should validate that the string is the right length first...
You can try a regular expression and put this inside an extension method ToMaskedString()
public static class StringExtensions
{
public static string ToMaskedString(this String value)
{
var pattern = "^(/d{2})(/d{3})(/d*)$";
var regExp = new Regex(pattern);
return regExp.Replace(value, "$1-$2-$3");
}
}
Then call
respne.Write(value.ToMaskedString());
I wrote a quick extension method for same / similar purpose (similar in a sense that there's no way to skip characters).
Usage:
var testString = "12345";
var maskedString = testString.Mask("##.## #"); // 12.34 5
Method:
public static string Mask(this string value, string mask, char substituteChar = '#')
{
int valueIndex = 0;
try
{
return new string(mask.Select(maskChar => maskChar == substituteChar ? value[valueIndex++] : maskChar).ToArray());
}
catch (IndexOutOfRangeException e)
{
throw new Exception("Value too short to substitute all substitute characters in the mask", e);
}
}
Maybe something like
string result = str.SubString(0, 2) + "-" + str.SubString(2, 3) + "-" + str.SubString(7);
str being the "11312000011103" string
Here's a C# 8 approach you can take:
Response.Write($"{value[..2]}-{value[2..5]}-{value[^6..]}");
I've complemented the Answer from #ESipalis
The extension method accepts a Array of chars to be replaced
public static string Mask(this string value, string mask, char[] substituteChar)
{
int valueIndex = 0;
try
{
return new string(mask.Select(maskChar => substituteChar.Contains(maskChar) ? value[valueIndex++] : maskChar).ToArray());
}
catch (IndexOutOfRangeException e)
{
return "#ERROR";
}
}
And you can call the extension:
yourString.Mask("AAA-999(SSS)","AS9".ToArray())

Getting rid of *consecutive* periods in a filename

I was wondering how I'd get rid of periods in a filename if i have a filename like:
Test....1.txt to look like Test 1.txt ? I do NOT want files like : 1.0.1 Test.txt to be touched. Only files with consecutive periods should be replaced with a space. Any ideas?
This is my current code but as you can see, it replaces every period aside from periods in extension names:
public void DoublepCleanUp(List<string> doublepFiles)
{
Regex regExPattern2 = new Regex(#"\s{2,}");
Regex regExPattern4 = new Regex(#"\.+");
Regex regExPattern3 = new Regex(#"\.(?=.*\.)");
string replace = " ";
List<string> doublep = new List<string>();
var filesCount = new Dictionary<string, int>();
try
{
foreach (string invalidFiles in doublepFiles)
{
string fileOnly = System.IO.Path.GetFileName(invalidFiles);
string pathOnly = System.IO.Path.GetDirectoryName(fileOnly);
if (!System.IO.File.Exists(fileOnly))
{
string filewithDoublePName = System.IO.Path.GetFileName(invalidFiles);
string doublepPath = System.IO.Path.GetDirectoryName(invalidFiles);
string name = System.IO.Path.GetFileNameWithoutExtension(invalidFiles);
//string newName = name.Replace(".", " ");
string newName = regExPattern4.Replace(name, replace);
string newName2 = regExPattern2.Replace(newName, replace);
string filesDir = System.IO.Path.GetDirectoryName(invalidFiles);
string fileExt = System.IO.Path.GetExtension(invalidFiles);
string fileWithExt = newName2 + fileExt;
string newPath = System.IO.Path.Combine(filesDir, fileWithExt);
System.IO.File.Move(invalidFiles, newPath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = doublepPath;
clean.Cells[1].Value = filewithDoublePName;
clean.Cells[2].Value = fileWithExt;
dataGridView1.Rows.Add(clean);
}
else
{
if (filesCount.ContainsKey(fileOnly))
{
filesCount[fileOnly]++;
}
else
{
filesCount.Add(fileOnly, 1);
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(fileOnly),
filesCount[fileOnly].ToString(),
System.IO.Path.GetExtension(fileOnly));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fileOnly), newFileName);
System.IO.File.Move(fileOnly, newFilePath);
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = fileOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
}
catch(Exception e)
{
//throw;
StreamWriter doublepcleanup = new StreamWriter(#"G:\DoublePeriodCleanup_Errors.txt");
doublepcleanup.Write("Double Period Error: " + e + "\r\n");
doublepcleanup.Close();
}
}
string name = "Text...1.txt";
Regex r = new Regex("[.][.]+");
string result = r.Replace(name, " ");
Well, to do that with a string:
string st = "asdf..asdf...asfd...asdf.asf.asdf.s.s";
Regex r = new Regex("\\.\\.+");
st = r.Replace(st, " ");
This will replace any instance of 2 or more '.'s with a space.
I would throw this into a method:
public static string StringReplace(string original,
string regexMatch, string replacement) {
Regex r = new Regex(regexMatch);
return r.Replace(original, replacement);
}
How about this?
string newFileName = String.Join(".", fileName.Split('.').Select(p => !String.IsNullOrEmpty(p) ? p : " ").ToArray())
Why not use something like this?
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", " ");
static string CleanUpPeriods(string filename)
{
StringBuilder sb = new StringBuilder();
if (filename.Length > 0) sb.Append(filename[0]);
for (int i = 1; i < filename.Length; i++)
{
char last = filename[i - 1];
char current = filename[i];
if (current != '.' || last != '.') sb.Append(current);
}
return sb.ToString();
}
You could use use regular expressions, something like this
string fileName = new Regex(#"[.][.]+").Replace(oldFileName, "");
Continuing from dark_charlie's solution, isn't
string newName = name;
while (newName.IndexOf("..") != -1)
newName = newName.Replace("..", ".");
enough?
I have tested this code on a number of cases, and it appears to exhibit the requested behavior.
private static string RemoveExcessPeriods(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
// If there are no consecutive periods, then just get out of here.
if (!text.Contains(".."))
return text;
// To keep things simple, let's separate the file name from its extension.
string extension = Path.GetExtension(text);
string fileName = Path.GetFileNameWithoutExtension(text);
StringBuilder result = new StringBuilder(text.Length);
bool lastCharacterWasPeriod = false;
bool thisCharacterIsPeriod = fileName.Length > 0 && fileName[0] == '.';
bool nextCharacterIsPeriod;
for (int index = 0; index < fileName.Length; index++)
{
// Includes both the extension separator and other periods.
nextCharacterIsPeriod = fileName.Length == index + 1 || fileName[index + 1] == '.';
if (!thisCharacterIsPeriod)
result.Append(fileName[index]);
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod && !nextCharacterIsPeriod)
result.Append('.');
else if (thisCharacterIsPeriod && !lastCharacterWasPeriod)
result.Append(' ');
lastCharacterWasPeriod = thisCharacterIsPeriod;
thisCharacterIsPeriod = nextCharacterIsPeriod;
}
return result.ToString() + extension;
}
I just made a change to handle some edge cases. Here are some test results for this version.
"Test....1.txt" => "Test 1.txt"
"1.0.1..Test.txt" => "1.0.1 Test.txt"
"Test......jpg" => "Test .jpg"
"Test.....jpg" => "Test .jpg"
"one.pic.jpg" => "one.pic.jpg"
"one..pic.jpg" => "one pic.jpg"
"one..two..three.pic.jpg" => "one two three.pic.jpg"
"one...two..three.pic.jpg" => "one two three.pic.jpg"
"one..two..three.pic..jpg" => "one two three.pic .jpg"
"one..two..three..pic.jpg" => "one two three pic.jpg"
"one..two..three...pic...jpg" => "one two three pic .jpg"
Combining some other answers...
static string CleanUpPeriods(string filename)
{
string extension = Path.GetExtension(filename);
string name = Path.GetFileNameWithoutExtension(filename);
Regex regex = new Regex(#"\.\.+");
string s = regex.Replace(name, " ").Trim();
if (s.EndsWith(".")) s = s.Substring(0, s.Length - 1);
return s + extension;
}
Sample Output
"Test........jpg" -> "Test.jpg"
"Test....1.jpg" -> "Test 1.jpg"
"Test 1.0.1.jpg" -> "Test 1.0.1.jpg"
"Test..jpg" -> "Test.jpg"
void ReplaceConsecutive(string src, int lenght, string replace)
{
char last;
int count = 0;
StringBuilder ret = new StringBuilder();
StringBuilder add = new StringBuilder();
foreach (char now in src)
{
if (now == last)
{
add.Append(now);
if (count > lenght)
{
ret.Append(replace);
add = new StringBuilder();
}
count++;
}
else
{
ret.Append(add);
add = new StringBuilder();
count = 0;
ret.Append(now);
}
}
return ret.ToString();
}
Untested, but this should work.
src is the string you want to check for consecutives, lenght is the number of equal chars followed by each other until they get replaced with replace.
This is AFAIK also possible in Regex, but I'm not that good with Regex's that I could do this.

RowFilter LIKE operation

I know that the following is not allowed as a row filter
'canada%.txt' or 'canada*.txt'
and I guess I can rewrite my filter as
file_name like 'Canada%' and file_name like '%.txt'
should work.
But is there an easier way instead of determing where the % is and spliting the string?
I don't believe that CHARINDEX is allowed in the filter expression.
You might try to dynamically build the filter string from C# (very much untested, but here's a possible syntax):
//split the original string using the wildcard as the delimiter
string[] f = s.Split('%');
//use the resulting array to build the resultstring
string resultstring = 'file_name like "' + f[0] + '%" and file_name like "%' + f[1] + '"'
//view.RowFilter = resultstring;
Here is the solution that I came up with
private string CreateRowFilter(string remoteFilePattern)
{
string[] pattern = remoteFilePattern.Split(new char[] { '*', '%' });
int length = pattern.GetUpperBound(0);
if (length == 0)
{
return String.Format("Name = '{0}'", pattern[0]);
}
StringBuilder fileter = new StringBuilder(
String.Format("Name LIKE '{0}*' ", pattern[0]));
for (int segment = 1; segment < length; segment++)
{
fileter.Append(
String.Format("AND Name LIKE '*{0}*' ", pattern[segment]));
}
if(String.IsNullOrEmpty(pattern[length]) == false)
{
fileter.Append(
String.Format("AND Name LIKE '*{0}' ", pattern[length]));
}
return fileter.ToString();
}

Categories