How to find string with role format in C#? - c#

I'm want to find string have format like:
numbers.H numbers.numbers'
Example:
1H 34'
4H 89'
I tried this code:
string format;
int[] numbers = new int[10] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
foreach(var values in numbers)
{
format = values + "H " + values + values + "'";
}
NOTE: this code seems to fail. I code to you can't easy understand my problem.
So, if my sourceString have values like: 4H 89'.
I want to check this values a have format like numbers.H numbers.numbers'
At this time, I analysis like:
4 is numbers. H . 8 is numbers. 9 is numbers. =====> Correct format.
My code can't find this string. Can anybody have any method to resolve my problem?
Thanks.

Try this:
string input = "9H 99";
if (Regex.Match(input.ToUpper(), #"\d[A-Z]\s\d\d").Success)
{
//Match
}
else
{
//Not
}

Can be simplified using Linq or Regex, may be this can be helpful
string[] stringFormat = new string[7] { "1H 34'", "4H 89'", "4H 89", "42 89", "4H 8H'", "345 t3", "4H 333'" };
List<string> requiredFormattedStrings = new List<string>();
foreach (var stringValue in stringFormat)
{
string[] val = stringValue.Split(' ');
if ((val[0].Length == 2 && val[0].EndsWith("H")) && (val[1].Length == 3 && val[1].EndsWith("'")))
{
bool isNumber = Char.IsDigit(val[0], 0);
if (isNumber)
{
string secondString = val[1].Substring(0, 2);
bool isNumber2 = secondString.All(c => Char.IsDigit(c));
if(isNumber2)
{
requiredFormattedStrings.Add(stringValue);
}
}
}
}
OUTPUT
1H 34' ,4H 89'

#Dr. Stitch answer is best. If you want to understand the regex pattern.
string input = "9H 99";
if (Regex.Match(input.ToUpper(), #"\d\\H [0-9]{2}").Success)
//This is the pattern if you get only H or else replace '\\H' with'[A-Z]'.
//If you also get small case then add [a-zA-Z]
{
//Match
}
else
{
//Not
}

Related

Get count of unique characters between first and last letter

I'm trying to get the unique characters count that are between the first and last letter of a word. For example: if I type Yellow the expected output is Y3w, if I type People the output should be P4e and if I type Money the output should be M3y. This is what I tried:
//var strArr = wordToConvert.Split(' ');
string[] strArr = new[] { "Money","Yellow", "People" };
List<string> newsentence = new List<string>();
foreach (string word in strArr)
{
if (word.Length > 2)
{
//ignore 2-letter words
string newword = null;
int distinctCount = 0;
int k = word.Length;
int samecharcount = 0;
int count = 0;
for (int i = 1; i < k - 2; i++)
{
if (word.ElementAt(i) != word.ElementAt(i + 1))
{
count++;
}
else
{
samecharcount++;
}
}
distinctCount = count + samecharcount;
char frst = word[0];
char last = word[word.Length - 1];
newword = String.Concat(frst, distinctCount.ToString(), last);
newsentence.Add(newword);
}
else
{
newsentence.Add(word);
}
}
var result = String.Join(" ", newsentence.ToArray());
Console.WriteLine("Output: " + result);
Console.WriteLine("----------------------------------------------------");
With this code I'm getting the expect output for Yellow, but seems that is not working with People and Money. What can I do to fix this issue or also I'm wondering is maybe there is a better way to do this for example using LINQ/Regex.
Here's an implementation that uses Linq:
string[] strArr = new[]{"Money", "Yellow", "People"};
List<string> newsentence = new List<string>();
foreach (string word in strArr)
{
if (word.Length > 2)
{
// we want the first letter, the last letter, and the distinct count of everything in between
var first = word.First();
var last = word.Last();
var others = word.Skip(1).Take(word.Length - 2);
// Case sensitive
var distinct = others.Distinct();
// Case insensitive
// var distinct = others.Select(c => char.ToLowerInvariant(c)).Distinct();
string newword = first + distinct.Count().ToString() + last;
newsentence.Add(newword);
}
else
{
newsentence.Add(word);
}
}
var result = String.Join(" ", newsentence.ToArray());
Console.WriteLine(result);
Output:
M3y Y3w P4e
Note that this doesn't take account of case, so the output for FiIsSh is 4.
Maybe not the most performant, but here is another example using linq:
var words = new[] { "Money","Yellow", "People" };
var transformedWords = words.Select(Transform);
var sentence = String.Join(' ', transformedWords);
public string Transform(string input)
{
if (input.Length < 3)
{
return input;
}
var count = input.Skip(1).SkipLast(1).Distinct().Count();
return $"{input[0]}{count}{input[^1]}";
}
You can implement it with the help of Linq. e.g. (C# 8+)
private static string EncodeWord(string value) => value.Length <= 2
? value
: $"{value[0]}{value.Substring(1, value.Length - 2).Distinct().Count()}{value[^1]}";
Demo:
string[] tests = new string[] {
"Money","Yellow", "People"
};
var report = string.Join(Environment.NewLine, tests
.Select(test => $"{test} :: {EncodeWord(test)}"));
Console.Write(report);
Outcome:
Money :: M3y
Yellow :: Y3w
People :: P4e
A lot of people have put up some good solutions. I have two solutions for you: one uses LINQ and the other does not.
LINQ, Probably not much different from others
if (str.Length < 3) return str;
var midStr = str.Substring(1, str.Length - 2);
var midCount = midStr.Distinct().Count();
return string.Concat(str[0], midCount, str[str.Length - 1]);
Non-LINQ
if (str.Length < 3) return str;
var uniqueLetters = new Dictionary<char, int>();
var midStr = str.Substring(1, str.Length - 2);
foreach (var c in midStr)
{
if (!uniqueLetters.ContainsKey(c))
{
uniqueLetters.Add(c, 0);
}
}
var midCount = uniqueLetters.Keys.Count();
return string.Concat(str[0], midCount, str[str.Length - 1]);
I tested this with the following 6 strings:
Yellow
Money
Purple
Me
You
Hiiiiiiiii
Output:
LINQ: Y3w, Non-LINQ: Y3w
LINQ: M3y, Non-LINQ: M3y
LINQ: P4e, Non-LINQ: P4e
LINQ: Me, Non-LINQ: Me
LINQ: Y1u, Non-LINQ: Y1u
LINQ: H1i, Non-LINQ: H1i
Fiddle
Performance-wise I'd guess they're pretty much the same, if not identical, but I haven't run any real perf test on the two approaches. I can't imagine they'd be much different, if at all. The only real difference is that the second route expands Distinct() into what it probably does under the covers anyway (I haven't looked at the source to see if that's true, but that's a pretty common way to get a count of . And the first route is certainly less code.
I Would use Linq for that purpose:
string[] words = new string[] { "Yellow" , "People", "Money", "Sh" }; // Sh for 2 letter words (or u can insert 0 and then remove the trinary operator)
foreach (string word in words)
{
int uniqeCharsInBetween = word.Substring(1, word.Length - 2).ToCharArray().Distinct().Count();
string result = word[0] + (uniqeCharsInBetween == 0 ? string.Empty : uniqeCharsInBetween.ToString()) + word[word.Length - 1];
Console.WriteLine(result);
}

Split Text file with fixed width with different sizes

I am stuck on a problem where I need to split a file with fixed width. Each field can be identified by its first character.
The file contains multiple format for example, the first row's format is {1, 11, 12} while second row's format is {1, 10, 12}. Both are identified with the first character.
AFirstField SecondFields
BBField SecondFields
However, sometimes a row can come with less characters like below.
AFirstField S
What I have tried so far is using text parser getting the current line and check the first character to decide the format, but the application falls over because sometimes rows have less data on them, like the A example above.
string[] data;
using (TextFieldParser myReader = new TextFieldParser(filePath))
{
myReader.TextFieldType = FieldType.FixedWidth;
while (!myReader.EndOfData)
{
currentLine = myReader.ReadLine();
recordType = currentLine[0].ToString();
if (!recordType.Equals("H"))
{
myReader.FieldWidths = returnLineFormat();
myReader.HasFieldsEnclosedInQuotes = true;
data = myReader.ReadFields();
//if (recordType.Equals("R"))
//{
// ISD.Add(data);
//}
}
}
}
private int[] returnLineFormat()
{
int[] format = null;
if ((recordType == "A"))
{
format = new int[] { 1, 11, 12};
}
else if ((recordType == "B"))
{
format = new int[] { 1, 10, 12};
}
return format;
}
These are the errors I am getting cause of row having less stuff:
Line 3 cannot be parsed using the current FieldWidths.
Is there a way around this problem?
Try this. It should work
static int[] returnLineFormat(string recordType)
{
int[] format = null;
if ((recordType == "A"))
{
format = new int[] { 1, 11, 12 };
}
else if ((recordType == "B"))
{
format = new int[] { 1, 10, 12 };
}
return format;
}
static void Main(string[] args)
{
string[] data;
using (TextFieldParser myReader = new TextFieldParser(#"TextParserExample.txt"))
{
myReader.TextFieldType = FieldType.FixedWidth;
while (!myReader.EndOfData)
{
var recordType = myReader.PeekChars(1);
if (!recordType.Equals("H"))
{
var lineLength = myReader.PeekChars(1000).Length;
var currentLine = myReader.ReadLine();
var lengths = returnLineFormat(recordType);
lengths[2] = lineLength - (lengths[0] + lengths[1]);
myReader.FieldWidths = lengths;
myReader.HasFieldsEnclosedInQuotes = true;
data = myReader.ReadFields();
}
}
}
}

Find a fixed length string with specific string part in C#

I want to find a string of fixed length with specific substring. But I need to do it like we can do in SQL queries.
Example:
I have strings like -
AB012345
AB12345
AB123456
AB1234567
AB98765
AB987654
I want to select strings that have AB at first and 6 characters afterwards. Which can be done in SQL by SELECT * FROM [table_name] WHERE [column_name] LIKE 'AB______' (6 underscores after AB).
So the result will be:
AB012345
AB123456
AB987654
I need to know if there is any way to select strings in such way with C#, by using AB______.
You can use Regular Expressions to filter the result:
List<string> sList = new List<string>(){"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"};
var qry = sList.Where(s=>Regex.Match(s, #"^AB\d{6}$").Success);
Considering you have an string array:
string[] str = new string[3]{"AB012345", "A12345", "AB98765"};
var result = str.Where(x => x.StartsWith("AB") && x.Length == 8).ToList();
The logic is if it starts with AB, and its length is 8. It is your best match.
this should do it
List<string> sList = new List<string>(){
"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"};
List<string> sREsult = sList.Where(x => x.Length == 8 && x.StartsWith("AB")).ToList();
first x.Length == 8 determines the length and x.StartsWith("AB") determines the required characters at the start of the string
This can be achieved by using string.Startwith and string.Length function like this:
public bool CheckStringValid (String input)
{
if (input.StartWith ("AB") && input.Length == 8)
{
return true;
}
else
{
return false;
}
}
This will return true if string matches your criteria.
Hope this helps.
var strlist = new List<string>()
{
"AB012345",
"AB12345",
"AB123456",
"AB1234567",
"AB98765",
"AB987654"
};
var result = strlist.Where(
s => (s.StartsWith("AB") &&(s.Length == 8))
);
foreach(var v in result)
{
Console.WriteLine(v.ToString());
}

Array 11th index

Ok so I was reworking the current infrastructure for my AI and I created it into an array. But i'm not sure how to get the 11th value to be recognized in the array "dictonary"
Here is the code!
string name = "Jarvis";
string[] dictionary = new string[] { "hello", "how", "are", "you", "sup", "wake", "up", "daddys", "home", "what", "version", "whats", "your" };
bool helloflag = false;
void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
string code = "";
//ResultText = "Hello how are you"
string[] words = e.Result.Text.Split(' ');
//words = ["Hello", "how", "are", "you"]
foreach (string word in words)
{
for (int index = 0; index < dictionary.Count(); index++)
{
if (word == dictionary[index])
{
code += index.ToString();
}
}
}
//code = "123"; //how are you
//code = "236"; //are you up
//HELLO
if ((code == "0") || (code == "4"))
{
Jarvis.Speak("Hello sir");
helloflag = true;
} else if ((helloflag == true ) && (code == "123"))
{
Jarvis.Speak("im good sir");
helloflag = false;
}
This is part of the .NET speech API, but is using an array to call the words you say.
When you're adding to code, you need to put a separator between the codes. Otherwise, you can't tell whether 12 is word 1 followed by word 2, or word 12. E.g.
code += index.toString() + " ";
Then you can do things like:
if (code == "10 9 2 3 ") // whats version are you
Don't forget the space at the end.
Prob it is more flexible to store your code values in array, e.g.:
var code = new List<int>();
....
code.Add(index);
...
if(code.SequenceEqual(new int[] {1, 2, 3})
{
...

Isolate characters from string

So I have a string called today with the value "nick_george_james"
it looks like this
string today = "_nick__george__james_";
how can i isolate the text between the '_' into a new string? i want to get the 3 names into seperate strings so that in the end i have name1, name2, name3 with the values nick, george and james
my application is written in c#
use string.Split
string[] array = today.Split('_');
After editing your question, I realized that you have multiple _ in your string. You should try the following.
string[] array = today.Split("_".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
Or
string[] array = today.Split(new []{"_"}, StringSplitOptions.RemoveEmptyEntries);
Later your array will contain:
array[0] = "nick";
array[1] = "george";
array[2] = "james";
string[] array = today.Split('_');
name1=array[0];
name2=array[1];
name3=array[2];
Thought of coming up with an idea other than string.Split.
string today = "_nick__george__james_";
//Change value nNoofwordstobeFound accordingly
int nNoofwordstobeFound = 3;
int nstartindex = 0;
int nEndindex = 0;
int i=1;
while (i <= nNoofwordstobeFound)
{
Skip:
nstartindex = today.IndexOf("_",nEndindex);
nEndindex = today.IndexOf("_", nstartindex + 1);
string sName = today.Substring(nstartindex + 1, nEndindex - (nstartindex + 1));
if (sName == "")
{
goto Skip;
}
else
{
//Do your code
//For example
string abc= sName;
}
i++;
}
I'd still prefer string.split method over this anytime.
string[] nameArray = today.Split('_');
Here you will get a array of names. You can get each name from by specifying index positions of the nameArray.
ie Now the the nameArray contains values as below
nameArray[0] = "nick", nameArray[1] = "george", nameArray[2] = "james"

Categories