Check Multiple Contains() and store the value dynamically - c#

I have a string function in which i have to check multiple characters. My code is
if(str.Contains("R") || str.Contains("f") || str.Contains("W") )
{
string letter= "";
}
My question is if string contains R then it has to be stored in letter variable, if f contains it has to be stored. How can I achieve it by not using multiple if conditions??

You could use string.IndexOfAny to find the position of one of the letters
int pos = str.IndexOfAny(new char[] {'R','f','W'});
if(pos >= 0)
{
string letter = str[pos].ToString();
....
}

Perhaps you want something like this?
string str = "abcRefg";
var letters = new[] { "R", "f", "W" };
string foundLetter = null;
foreach (var letter in letters)
{
if (str.Contains(letter))
{
foundLetter = letter;
break;
}
}

Since you need to know which characters str contains, you can use the Enumerable.Intersect extension method.
char[] characters = {'R', 'f', 'W'};
var common = str.Intersect(characters).ToList();
foreach(char c in common)
{
}

Related

Remove Identical Words from a string array

The goal is to remove a certain prefix word from a string in string array example: ["Market1", "Market2", "Market3"]. The prefix word Market is dominant in string array, so we have to remove Market from string array so the result should be ["1", "2", "3"]. Please take note that the Market prefix word in string could be anything.
Look for the first character that is not identical among all strings and select a substring starting at that position to remove the prefix.
string[] words = new string[] { "Market1", "Market2", "Market3" };
int i = 0;
while (words.All(word => word.Length > i && word[i] == words[0][i])) ++i;
var wordsWithoutPrefixes = words.Select(word => word.Substring(i)).ToArray();
Make a delimited string and then replace all the Market with an empty string and then split the string to an array.
string[] arr = new string[] { "Market1", "Market2", "Market3" };
string[] result = string.Join(".", arr).Replace("Market", "").Split('.');
Loop through each item in the array and for each item chop off the beginning the start matches.
var commonPrefix = "Market";
for (int i = 0; i < arr.length, i++) {
if(arr[i].IndexOf(commonPrefix) == 0) {
arr[i] = arr[i].Substring(commonPrefix.Length);
}
}
You can use LINQ:
string[] myArray = ["Market1", "Market2", "Market3"];
string prefix = myArray[0];
foreach (var s in myArray)
{
while (!s.StartsWith(prefix))
prefix = prefix.Substring(0, prefix.Length - 1);
}
string[] result = myArray
.Select(s => s.Substring(prefix.Length))
.ToArray();
Loop through the array of string and replace the substring containing prefix with an empty substring.
string[] s=new string[]{"Market1","Market2","Market3"};
string prefix="Market";
foreach(var x in s)
{
if(x.Contains(prefix))
{
x=x.Replace(prefix,"");
}
}

Assign new value to a string index

I need to convert the characters a, e, i, o, u in the user input string to the assigned symbols. Below is what I have so far.
School assignment
First prompt the user for the encrypted text string. Validate that this is not left blank. Send this text string into a custom method you will create that will decipher it. Once it is deciphered, return this text string to the main where you will output both the encrypted and decrypted strings.
To decipher the text string you must perform the following character replacements:
# = a
# = e
^ = i
* = o
+ = u
My current code
public static string Decipher (string code)
{
char[] array = code.ToCharArray();
for (int i = 0; i < code.Length; i++)
{
if (code.Contains("#") && code.Contains("#") && code.Contains("^") &&
code.Contains("*") && code.Contains("+"))
{
}
}
Every time you go through this for loop, it will evaluate true if the string contains #, #, ^, * and + anywhere in the string. So if your string is missing any of these symbols, your if statement will evaluate to false and nothing will happen.
Luckily you can simplify this pretty easily. One way you can do this is to convert your string to a char[] array and break your logic into multiple if-else statements, or a single switch statement, for example:
public static string Decipher (string code)
{
char[] codeArray = code.ToCharArray(); // convert your code string to a char[] array
for (int i = 0; i < codeArray.Length; i++)
{
switch (codeArray[i]) // Get the char at position i in the array
{
case '#': // if the character at i is '#'
codeArray[i] = 'a'; // Change the character at i to 'a'
break; // break out of the switch statement - we don't need to evaluate anything else
case '#': // if the character at i is '#'
codeArray[i] = 'e'; // Change the character at i to 'e'
break; // break out of the switch statement - we don't need to evaluate anything else
// repeat for everything else you need to replace!
}
}
return new String(codeArray); // Once you're all done, create a string from your deciphered array and return it
}
There are a bunch of different ways of doing it. Doing string concatenation in a loop (as shown by #Acex) is generally frowned upon; it spins out a lot of "garbage" and can slow things down. The Stringbuilder class is generally a better option. My code uses Stringbuilders (well, the same one over and over - I clear it in between).
Here are several ways of doing the same thing:
const string encoded = "H#ll*, H*w #r# y*+?";
//good old fashioned C-style/brute force:
var buf = new StringBuilder();
foreach (var c in encoded){
switch(c){
case '#':
buf.Append('a');
break;
case '#':
buf.Append('e');
break;
case '^':
buf.Append('i');
break;
case '*':
buf.Append('o');
break;
case '+':
buf.Append('u');
break;
default:
buf.Append(c);
break;
}
}
var result = buf.ToString();
//using a lookup table (easily extensible)
buf.Clear();
var decodeDict = new Dictionary<char, char>{
{'#', 'a'},
{'#', 'e'},
{'^', 'i'},
{'*', 'o'},
{'+', 'u'},
};
foreach (var c in encoded){
if (decodeDict.Keys.Contains(c)){
buf.Append(decodeDict[c]);
} else {
buf.Append(c);
}
}
result = buf.ToString();
//something completely different
//instead of iterating through the string, iterate through the decoding dictionary
buf.Clear();
var working = new StringBuilder(encoded.Length);
working.Append(encoded);
foreach (var pair in decodeDict){
working.Replace(pair.Key, pair.Value);
}
result = working.ToString();
In each case, result holds, well, the result. Put a breakpoint right after each result assignment and see what's happened.
I'm not providing a lot of comments, step through the code, look up the classes and figure out what I'm doing (you are the student, after all).
It's really as simple as doing this:
public static string Decipher(string code)
{
var map = new Dictionary<char, char>()
{
{ '#', 'a' },
{ '#', 'e' },
{ '^', 'i' },
{ '*', 'o' },
{ '+', 'u' },
};
char[] array = code.ToCharArray();
array = array.Select(x => map.ContainsKey(x) ? map[x] : x).ToArray();
return new string(array);
}
Now you can do this:
string cipher = "*+tp+t";
string plain = Decipher(cipher);
Console.WriteLine(cipher);
Console.WriteLine(plain);
This outputs:
*+tp+t
output
For the sake of alternative
And when you will be allowed to use existing methods.
you can write something like this:
private Dictionary<char, char> mapping = new Dictionary<char, char>()
{
{ '#', 'a' },
{ '#', 'e' },
{ '^', 'i' },
{ '*', 'o' },
{ '+', 'u' },
};
private string Decrypt(string encryptedString) =>
string.Concat(encryptedString.Select(s => mapping.ContainsKey(s) ? mapping[s] : s));
And usage:
string result = Decrypt(encryptedString);
References: DotNetFiddle Example

Spliting a string by capital letters except for certain keywords

The following function splits a string at any uppercase character found within the string.
public static string ToSentence(this string input)
{
var list = new List<char>();
for (var i = 0; i < input.ToCharArray().Length; i++)
{
var c = input.ToCharArray()[i];
foreach (char c1 in i > 0 && char.IsUpper(c) ? new[] {' ', c} : new[] {c})
list.Add(c1);
}
return new string(list.ToArray());
}
In my code, this function is being used in conjunction with another function that retrieves the name of the current method in code. I'm finding this function breaks when a method name contains multiple capital letters sequentially.
For example, if I have a method called GetDatabaseIDE() it would return as "Get Database I D E"
How can I change my ToSentence function so that it accepts a list of keywords that won't be split (For example, I D E becomes IDE)?
Why not try Regex ? Demo # https://dotnetfiddle.net/FsPZ9O
1. ([A-Z]+) - match all leading uppercase char.
2. ([^A-Z])* - followed with zero-or-more of any that isn't an uppercase char.
Regex.Matches("GetDatabaseIDE", #"([A-Z]+)([^A-Z])*").Cast<Match>().Select(m => m.Value);
TakeWhile method can be useful here, once you find an upper case character, you can take the following upper case characters:
for (var i = 0; i < input.Length; i++)
{
var c = input[i];
if(char.IsUpper(c))
{
var charsToAdd = input.Skip(i).TakeWhile(char.IsUpper).ToArray();
if(charsToAdd.Length > 1)
{
i += charsToAdd.Length - 1;
}
if(i > 0) list.Add(' ');
list.Add(charsToAdd);
}
else
{
list.Add(c);
}
}
you can add keywords you want to skip:
public static string ToSentence(string input)
{
var list = new List<char>();
for (var i = 0; i < input.ToCharArray().Length; i++)
{
if(input.IndexOf("IDE",i,input.Length-i)==i){
list.AddRange(" IDE");
i+=2;
}
else{
var c = input.ToCharArray()[i];
foreach (char c1 in i > 0 && char.IsUpper(c) ? new[] {' ', c} : new[] {c})
list.Add(c1);
}
}
return new string(list.ToArray());
}
watch it here
This will work for your example, you will have to tweak it if your method names have numbers in them
using System.Text.RegularExpressions;
public static string GetNiceName(string testString)
{
var pattern = "([A-Z][a-z]+)|([A-Z]+)";
var result = new List<string>();
foreach (Match m in Regex.Matches(testString, pattern))
{
result.Add(m.Groups[0].Value);
}
return string.Join(" ", result);
}

Use more than one character to replace other

I have a app and in this app it is possible with a function to replace some characters in a word with a other character
var newCharacter = "H";
if (/*something happens here and than the currentCharacter will be replaced*/)
{
// Replace the currentCharacter in the word with a random newCharacter.
wordString = wordString.Replace(currentCharacter, newCharacter);
}
now all the characters will be replaced with the code above with the "H". But i want more letters so by example the H, E, A, S
what is the best way to do this?
When i do this:
var newCharacter = "H" + "L" + "S";
it replaced the currentCharacter with H AND L AND S but i just want it to replace with H OR L OR S not all three
so if you have a word with HELLO and you want to replace the O with the newCharacter my output now is HELLHLS
O -> HLS
but O needs to be -> H or L or S
Here is a way to do using LINQ.You can add the characters you want to remove in the array excpChar
char[] excpChar= new[] { 'O','N' };
string word = "LONDON";
var result = excpChar.Select(ch => word = word.Replace(ch.ToString(), ""));
Console.WriteLine(result.Last());
The Replace function replaces all the occurences at once, this is not what we want. Let's do a ReplaceFirst function, only replacing the first occurence (one could make an extension method out of this):
static string ReplaceFirst(string word, char find, char replacement)
{
int location = word.IndexOf(find);
if (location > -1)
return word.Substring(0, location) + replacement + word.Substring(location + 1);
else
return word;
}
Then we can use a random generator to replace the target letter with different letters through successive calls of ReplaceFirst:
string word = "TpqsdfTsqfdTomTmeT";
char find = 'T';
char[] replacements = { 'H', 'E', 'A', 'S' };
Random random = new Random();
while (word.Contains(find))
word = ReplaceFirst(word, find, replacements[random.Next(replacements.Length)]);
word now may be EpqsdfSsqfdEomHmeS or SpqsdfSsqfdHomHmeE or ...
You can do like following :
string test = "abcde";
var result = ChangeFor(test, new char[] {'b', 'c'}, 'z');
// result = "azzde"
with ChangeFor :
private string ChangeFor(string input, IEnumerable<char> before, char after)
{
string result = input;
foreach (char c in before)
{
result = result.Replace(c, after);
}
return result;
}

C# split string but keep split chars / separators [duplicate]

I would like to split a string with delimiters but keep the delimiters in the result.
How would I do this in C#?
If the split chars were ,, ., and ;, I'd try:
using System.Text.RegularExpressions;
...
string[] parts = Regex.Split(originalString, #"(?<=[.,;])")
(?<=PATTERN) is positive look-behind for PATTERN. It should match at any place where the preceding text fits PATTERN so there should be a match (and a split) after each occurrence of any of the characters.
If you want the delimiter to be its "own split", you can use Regex.Split e.g.:
string input = "plum-pear";
string pattern = "(-)";
string[] substrings = Regex.Split(input, pattern); // Split on hyphens
foreach (string match in substrings)
{
Console.WriteLine("'{0}'", match);
}
// The method writes the following to the console:
// 'plum'
// '-'
// 'pear'
So if you are looking for splitting a mathematical formula, you can use the following Regex
#"([*()\^\/]|(?<!E)[\+\-])"
This will ensure you can also use constants like 1E-02 and avoid having them split into 1E, - and 02
So:
Regex.Split("10E-02*x+sin(x)^2", #"([*()\^\/]|(?<!E)[\+\-])")
Yields:
10E-02
*
x
+
sin
(
x
)
^
2
Building off from BFree's answer, I had the same goal, but I wanted to split on an array of characters similar to the original Split method, and I also have multiple splits per string:
public static IEnumerable<string> SplitAndKeep(this string s, char[] delims)
{
int start = 0, index;
while ((index = s.IndexOfAny(delims, start)) != -1)
{
if(index-start > 0)
yield return s.Substring(start, index - start);
yield return s.Substring(index, 1);
start = index + 1;
}
if (start < s.Length)
{
yield return s.Substring(start);
}
}
Just in case anyone wants this answer aswell...
Instead of string[] parts = Regex.Split(originalString, #"(?<=[.,;])") you could use string[] parts = Regex.Split(originalString, #"(?=yourmatch)") where yourmatch is whatever your separator is.
Supposing the original string was
777- cat
777 - dog
777 - mouse
777 - rat
777 - wolf
Regex.Split(originalString, #"(?=777)") would return
777 - cat
777 - dog
and so on
This version does not use LINQ or Regex and so it's probably relatively efficient. I think it might be easier to use than the Regex because you don't have to worry about escaping special delimiters. It returns an IList<string> which is more efficient than always converting to an array. It's an extension method, which is convenient. You can pass in the delimiters as either an array or as multiple parameters.
/// <summary>
/// Splits the given string into a list of substrings, while outputting the splitting
/// delimiters (each in its own string) as well. It's just like String.Split() except
/// the delimiters are preserved. No empty strings are output.</summary>
/// <param name="s">String to parse. Can be null or empty.</param>
/// <param name="delimiters">The delimiting characters. Can be an empty array.</param>
/// <returns></returns>
public static IList<string> SplitAndKeepDelimiters(this string s, params char[] delimiters)
{
var parts = new List<string>();
if (!string.IsNullOrEmpty(s))
{
int iFirst = 0;
do
{
int iLast = s.IndexOfAny(delimiters, iFirst);
if (iLast >= 0)
{
if (iLast > iFirst)
parts.Add(s.Substring(iFirst, iLast - iFirst)); //part before the delimiter
parts.Add(new string(s[iLast], 1));//the delimiter
iFirst = iLast + 1;
continue;
}
//No delimiters were found, but at least one character remains. Add the rest and stop.
parts.Add(s.Substring(iFirst, s.Length - iFirst));
break;
} while (iFirst < s.Length);
}
return parts;
}
Some unit tests:
text = "[a link|http://www.google.com]";
result = text.SplitAndKeepDelimiters('[', '|', ']');
Assert.IsTrue(result.Count == 5);
Assert.AreEqual(result[0], "[");
Assert.AreEqual(result[1], "a link");
Assert.AreEqual(result[2], "|");
Assert.AreEqual(result[3], "http://www.google.com");
Assert.AreEqual(result[4], "]");
A lot of answers to this! One I knocked up to split by various strings (the original answer caters for just characters i.e. length of 1). This hasn't been fully tested.
public static IEnumerable<string> SplitAndKeep(string s, params string[] delims)
{
var rows = new List<string>() { s };
foreach (string delim in delims)//delimiter counter
{
for (int i = 0; i < rows.Count; i++)//row counter
{
int index = rows[i].IndexOf(delim);
if (index > -1
&& rows[i].Length > index + 1)
{
string leftPart = rows[i].Substring(0, index + delim.Length);
string rightPart = rows[i].Substring(index + delim.Length);
rows[i] = leftPart;
rows.Insert(i + 1, rightPart);
}
}
}
return rows;
}
This seems to work, but its not been tested much.
public static string[] SplitAndKeepSeparators(string value, char[] separators, StringSplitOptions splitOptions)
{
List<string> splitValues = new List<string>();
int itemStart = 0;
for (int pos = 0; pos < value.Length; pos++)
{
for (int sepIndex = 0; sepIndex < separators.Length; sepIndex++)
{
if (separators[sepIndex] == value[pos])
{
// add the section of string before the separator
// (unless its empty and we are discarding empty sections)
if (itemStart != pos || splitOptions == StringSplitOptions.None)
{
splitValues.Add(value.Substring(itemStart, pos - itemStart));
}
itemStart = pos + 1;
// add the separator
splitValues.Add(separators[sepIndex].ToString());
break;
}
}
}
// add anything after the final separator
// (unless its empty and we are discarding empty sections)
if (itemStart != value.Length || splitOptions == StringSplitOptions.None)
{
splitValues.Add(value.Substring(itemStart, value.Length - itemStart));
}
return splitValues.ToArray();
}
Recently I wrote an extension method do to this:
public static class StringExtensions
{
public static IEnumerable<string> SplitAndKeep(this string s, string seperator)
{
string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None);
for (int i = 0; i < obj.Length; i++)
{
string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator;
yield return result;
}
}
}
I'd say the easiest way to accomplish this (except for the argument Hans Kesting brought up) is to split the string the regular way, then iterate over the array and add the delimiter to every element but the last.
To avoid adding character to new line try this :
string[] substrings = Regex.Split(input,#"(?<=[-])");
result = originalString.Split(separator);
for(int i = 0; i < result.Length - 1; i++)
result[i] += separator;
(EDIT - this is a bad answer - I misread his question and didn't see that he was splitting by multiple characters.)
(EDIT - a correct LINQ version is awkward, since the separator shouldn't get concatenated onto the final string in the split array.)
Iterate through the string character by character (which is what regex does anyway.
When you find a splitter, then spin off a substring.
pseudo code
int hold, counter;
List<String> afterSplit;
string toSplit
for(hold = 0, counter = 0; counter < toSplit.Length; counter++)
{
if(toSplit[counter] = /*split charaters*/)
{
afterSplit.Add(toSplit.Substring(hold, counter));
hold = counter;
}
}
That's sort of C# but not really. Obviously, choose the appropriate function names.
Also, I think there might be an off-by-1 error in there.
But that will do what you're asking.
veggerby's answer modified to
have no string items in the list
have fixed string as delimiter like "ab" instead of single character
var delimiter = "ab";
var text = "ab33ab9ab"
var parts = Regex.Split(text, $#"({Regex.Escape(delimiter)})")
.Where(p => p != string.Empty)
.ToList();
// parts = "ab", "33", "ab", "9", "ab"
The Regex.Escape() is there just in case your delimiter contains characters which regex interprets as special pattern commands (like *, () and thus have to be escaped.
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
string input = #"This;is:a.test";
char sep0 = ';', sep1 = ':', sep2 = '.';
string pattern = string.Format("[{0}{1}{2}]|[^{0}{1}{2}]+", sep0, sep1, sep2);
Regex regex = new Regex(pattern);
MatchCollection matches = regex.Matches(input);
List<string> parts=new List<string>();
foreach (Match match in matches)
{
parts.Add(match.ToString());
}
}
}
}
I wanted to do a multiline string like this but needed to keep the line breaks so I did this
string x =
#"line 1 {0}
line 2 {1}
";
foreach(var line in string.Format(x, "one", "two")
.Split("\n")
.Select(x => x.Contains('\r') ? x + '\n' : x)
.AsEnumerable()
) {
Console.Write(line);
}
yields
line 1 one
line 2 two
I came across same problem but with multiple delimiters. Here's my solution:
public static string[] SplitLeft(this string #this, char[] delimiters, int count)
{
var splits = new List<string>();
int next = -1;
while (splits.Count + 1 < count && (next = #this.IndexOfAny(delimiters, next + 1)) >= 0)
{
splits.Add(#this.Substring(0, next));
#this = new string(#this.Skip(next).ToArray());
}
splits.Add(#this);
return splits.ToArray();
}
Sample with separating CamelCase variable names:
var variableSplit = variableName.SplitLeft(
Enumerable.Range('A', 26).Select(i => (char)i).ToArray());
I wrote this code to split and keep delimiters:
private static string[] SplitKeepDelimiters(string toSplit, char[] delimiters, StringSplitOptions splitOptions = StringSplitOptions.None)
{
var tokens = new List<string>();
int idx = 0;
for (int i = 0; i < toSplit.Length; ++i)
{
if (delimiters.Contains(toSplit[i]))
{
tokens.Add(toSplit.Substring(idx, i - idx)); // token found
tokens.Add(toSplit[i].ToString()); // delimiter
idx = i + 1; // start idx for the next token
}
}
// last token
tokens.Add(toSplit.Substring(idx));
if (splitOptions == StringSplitOptions.RemoveEmptyEntries)
{
tokens = tokens.Where(token => token.Length > 0).ToList();
}
return tokens.ToArray();
}
Usage example:
string toSplit = "AAA,BBB,CCC;DD;,EE,";
char[] delimiters = new char[] {',', ';'};
string[] tokens = SplitKeepDelimiters(toSplit, delimiters, StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
{
Console.WriteLine(token);
}

Categories

Resources