How to check if a string has numbers and letters of alphabet - c#

I am wondering if strings have functionality that can see if a string contains words or words and other types of characters in general. (ideally I want to only consider strings that have readable sentences but that may too advanced) I am trying to count strings in a list that have that kind of text. I do not want to add to the count any strings that are only numbers, blank spaces, tabs or symbols (like ?, #, #) or even random letters unless there is at least some words contained in the string.
The strings will be initialised with "" so the code in the if statement - (this.ElementAt(i).getNotarised().ElementAt(j).getError() != "") - would be fine if there was no input at all. Unfortunately I am expecting some input in some case so this case also counts scenarios where there are only spaces, number, symbols or all of the 3 - which I do not want.
this is referring to a class inheriting from List
.getNotarised() returns a List
/** Find the highest/lowest amount of errors/solutions/suggestions/comments.
* If it's ASC then return the lowest to highest.
* If it's DESC then return the highest to lowest.
* Return a list with LOGS in the correct order.
* */
public List<LOG> highORlow(string asc_desc, string category)
{
int count = 0;
int[] array = new int[this.Count()];
for(int i = 0; i <= this.Count()-1; i++)
{
for(int j = 0; j <= this.ElementAt(i).getNotarised().Count()-1; j++)
{
if(this.ElementAt(i).getNotarised().ElementAt(j).getError() != "")
{
++count;
}
}
array[i] = count;
}
return new List<LOG>();
}

Point of interest:
string pattern = "[A-Za-z]{5}[0-9]{0}";
Regex xp = new Regex(pattern);
Use xp.IsMatch() to check if the pattern is matched.
/** Find the highest/lowest amount of errors/solutions/suggestions/comments.
* If it's true (ASC) then return the lowest to highest.
* If it's false (DESC) then return the highest to lowest.
* Return a list with LOGS in the correct order.
* */
public List<LOG> highORlow(bool asc_desc, string category)
{
int count = 0;
string pattern = "[A-Za-z]{5}[0-9]{0}";
Regex xp = new Regex(pattern);
Dictionary<LOG, int> array = new Dictionary<LOG, int>();
for (int i = 0; i <= this.Count() - 1; i++)
{
for (int j = 0; j <= this.ElementAt(i).getNotarised().Count() - 1; j++)
{
if (category == "ERROR")
{
if (xp.IsMatch(this.ElementAt(i).getNotarised().ElementAt(j).getError()))
{
++count;
continue;
}
}
if (category == "SOLUTION")
{
if (xp.IsMatch(this.ElementAt(i).getNotarised().ElementAt(j).getSolution()))
{
++count;
continue;
}
}
if (category == "SUGGESTION")
{
if (xp.IsMatch(this.ElementAt(i).getNotarised().ElementAt(j).getSuggestion()))
{
++count;
continue;
}
}
if (category == "COMMENT")
{
if (xp.IsMatch(this.ElementAt(i).getNotarised().ElementAt(j).getComment()))
{
++count;
continue;
}
}
}
array.Add(this.ElementAt(i), count);
count = 0;
}
List<LOG> list = new List<LOG>();
if(asc_desc)
{
foreach (KeyValuePair<LOG, int> v in array.OrderBy(key => key.Value))
{
list.Add(v.Key);
}
}
else
{
foreach (KeyValuePair<LOG, int> v in array.OrderByDescending(key => key.Value))
{
list.Add(v.Key);
}
}
return list;
}```

Related

String list contains of all sub-components

String list G is :
[0] : {"1,2,5"}
[1] : {"1,2,4,5,6"}
[2] : {"2,4,6"}
[3] : {"1,4,6"}
With the following commands, we conclude that "1,4" exists in the List G[3] :
if (G[i].Contains("1,4")) { //code here }
How to modify the above commands, that in addition feature (Contains), "1,4" exists in the List G[1]?
Program codes
for (int i = 0; i < candid.Count; i++)
{
foreach (TransactionTP b in transactions)
{
string search = candid[i];
var searchNumbers = search.Split(',').Select(int.Parse).ToList();
for (int j = 0; j < G.Count; j++)
{
IEnumerable<int> numbers = G[j].Split(',').Select(int.Parse);
int idx = 0;
foreach (var number in numbers)
{
if (number == searchNumbers[idx])
{
idx++;
}
if (idx == searchNumbers.Count)
{
arraye[i] = arraye[i] + (b.transactionUtility);
break;
}
}
}
}
}
Update:
The order of the searched term matters.
In order to preserve the ordering of the set you are matching go (4,1 in this case), you will need to evaluate each string, keeping track of where you are in the match.
string[] G = new[]
{
"1,2,5",
"1,2,4,5,6",
"2,4,6",
"1,4,6"
};
string search = "1,4";
var searchNumbers = search.Split(',').Select(int.Parse).ToList();
for (int i = 0; i < G.Length; i++)
{
// Convert the string into an enumeration of numbers
IEnumerable<int> numbers = G[i].Split(',').Select(int.Parse);
// Index to keep track of the search
int idx = 0;
// Loop through the input set sequentially
foreach (var number in numbers)
{
// Check if the input matches the next expected number
if (number == searchNumbers[idx])
{
idx++;
}
if (idx == searchNumbers.Count)
{
Console.WriteLine("String {0} matched", G[i]);
break;
}
}
}
Replace your single Contains call with a method that does this:
bool passes = false;
for(int i = 0; i < G.Length; i++)
{
List<string> temp = new List<string>();
if(G[i].Contains(","))
{
temp = G[i].Split(",");
}
else
{
temp = G[i];
}
if(temp.Contains("1") && temp.Contains("4")
{
passes = true;
}
}
return passes;
This eliminates the possibility of matching on "10" or "41" etc etc
It also will not care if your elements are sorted, even though you said they are. It will also match regardless of the number of entries between "1" and "4" in the list.
You could spice this up to take any number of inputs that you want to match before qualifying as a match, I'll leave that to you if you want to make it so.

Count similar adjacent items in List<string>

I'm trying to find similar adjacent items in List and count its number, e.g.:
List<string> list = new List<string> {"a", "a", "b", "d", "c", "c"};
Desired Output:
a = 2, c = 2
What I've done is use for loop to iterate over each element of the list and to see whether it has similar adjacent element, but understandably it gives ArgumentOutOfRangeException() because I don't know how to keep track of the position of the iterator so that it doesn't go out of bounds. Here's what I've done:
for (int j = 0; j < list.Count; j++)
{
if (list[j] == "b")
{
if ((list[j + 1] == "b") && (list[j - 1] == "b"))
{
adjacent_found = true;
}
}
}
Having said that, if there's another easier way to find similar adjacent elements in a List other than using for loop iteration, please advise. Thanks.
You can do something like this:
static IEnumerable<Tuple<string, int>> FindAdjacentItems(IEnumerable<string> list)
{
string previous = null;
int count = 0;
foreach (string item in list)
{
if (previous == item)
{
count++;
}
else
{
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
count = 1;
}
previous = item;
}
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
}
for (int i= 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
if (list[i] == list[j])
{
adjacent_found = true;
count++;
}
}
}
Check this:
Dictionary<char,int> dic=new Dictionary<char,int>();
for(int i=1;i<list.count;i++)
{
if(list[i]==list[i-1])
{
if(dic.ContainsKey(list[i]))
{
dic[list[i]]+=1;
}
else
{
dic.Add(list[i],2)
}
}
}
To avoid ArgumentOutOfRangeException use for (int j = 1; j < list.Count - 1; j++). Desired answer can't be achieved this way. Try this:
IEnumerable<Adjacent> CountAdjacents(List<string> source)
{
var result = new List<Adjacent>();
for (var i = 0; i < source.Count() - 1; i++)
{
if (source[i] == source[i + 1])
{
if (result.Any(x => x.Word == source[i]))
{
result.Single(x => x.Word == source[i]).Quantity++;
}
else
result.Add(new Adjacent
{
Word = source[i],
Quantity = 2
});
}
}
return result;
}
class Adjacent
{
public string Word;
public int Quantity;
}
Maintain an int array of 256 size, initialized to 1. Run a loop [O(n)] for i=0 to i-2, compare each char with the next char. If same then find the ascii value of the char and increment the corresponding value in array.
Hope this helps!

Sorting a List alphabetically and numerically

I've written a code that has a list and I want to sort the list alphabetically and numerically.
For example the first items in the list are
list[0] = "INPUT 10"
list[1] = "INPUT 5".
I want my list reorganized like this:
list[0] = "INPUT 5"
list[1] = "INPUT 10".
So basically my program gets checked items from a checked list box,stores them in a list, and I want it to reorganize the list alphabettically.
The checked list box has items like INPUT 1,INPUT 2,INPUT 3...and so fourth. Can anyone suggest me a way of how to go about this?
UPDATED CODE
I've updated my code and now this code splits the strings into INPUT and 10.The "q" list obtains the checked items in the input box,the string "s" array gets the splittd data from the q list. Then the "numbers" list gets only the number part of the string for example "INPUT 5",the number list will only get "5".Then I want to sort these numbers and build another string combining the sorted number list and the string "INPUT" and add it to the output checkedlistbox. My code isnt working though...any suggestions?It should sort the numbers but it doesnt...anyone have any suggestions of why this code isnt working? And I keep on getting error messages of the array being able to unhandle negative integers and what not.
List<string> q = new List<string>();
List<string> numbers = new List<string>();
private void button_ekle_Click(object sender, EventArgs e)
{
for (int k = clb_input.Items.Count - 1; k >= 0; k--)
{
if (clb_input.GetItemChecked(k) == true)
{
q.Add(clb_input.Items[k].ToString());
//clb_output.Items.Add(clb_input.Items[k]);
clb_input.Items.RemoveAt(k);
}
else { }
}
string[] s = new string[q.Count * 2];
//string[] numbers=new string[q.Count/2];
for (int t = 1; t <= q.Count * 2; t++)
{
if (q != null)
s = q[t - 1].ToString().Split(' ');
else { s[t] = null; }
}
for (int x = 1; x <= q.Count; x++)
{
if (s[2 * x - 1] != null)
{
numbers[x - 1] = s[2 * x - 1];
numbers.Sort();
clb_output.Items.Add("INPUT "+ numbers[x - 1].ToString());
}
else { numbers[x - 1] = null; }
}
}
What you need is Alphanumeric Sorting ( most commonly seen in windows explorer, the way files are sorted)
Code can be found here : http://www.dotnetperls.com/alphanumeric-sorting
Sample
class Program
{
static void Main()
{
string[] highways = new string[]
{
"100F",
"50F",
"SR100",
"SR9"
};
//
// We want to sort a string array called highways in an
// alphanumeric way. Call the static Array.Sort method.
//
Array.Sort(highways, new AlphanumComparatorFast());
//
// Display the results
//
foreach (string h in highways)
{
Console.WriteLine(h);
}
}
}
Output
50F
100F
SR9
SR100
Implementation
public class AlphanumComparatorFast : IComparer
{
public int Compare(object x, object y)
{
string s1 = x as string;
if (s1 == null)
{
return 0;
}
string s2 = y as string;
if (s2 == null)
{
return 0;
}
int len1 = s1.Length;
int len2 = s2.Length;
int marker1 = 0;
int marker2 = 0;
// Walk through two the strings with two markers.
while (marker1 < len1 && marker2 < len2)
{
char ch1 = s1[marker1];
char ch2 = s2[marker2];
// Some buffers we can build up characters in for each chunk.
char[] space1 = new char[len1];
int loc1 = 0;
char[] space2 = new char[len2];
int loc2 = 0;
// Walk through all following characters that are digits or
// characters in BOTH strings starting at the appropriate marker.
// Collect char arrays.
do
{
space1[loc1++] = ch1;
marker1++;
if (marker1 < len1)
{
ch1 = s1[marker1];
}
else
{
break;
}
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
do
{
space2[loc2++] = ch2;
marker2++;
if (marker2 < len2)
{
ch2 = s2[marker2];
}
else
{
break;
}
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
// If we have collected numbers, compare them numerically.
// Otherwise, if we have strings, compare them alphabetically.
string str1 = new string(space1);
string str2 = new string(space2);
int result;
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
{
int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
result = str1.CompareTo(str2);
}
if (result != 0)
{
return result;
}
}
return len1 - len2;
}
}
The simplest solution is to just left-pad the numerical values with a space to the same length.
List<string> lst = new List<string>
{
"Item 9",
"Item 999",
"Thing 999",
"Thing 5",
"Thing 1",
"Item 20",
"Item 10",
};
lst.Sort();
Output:
Item 9
Item 10
Item 20
Item 999
Thing 1
Thing 5
Thing 999
And you can always remove the extra white space used for padding after the sorting operation is performed.
You can use Sort with a Comparer like this:
List<string> q = new List<string>();
private void button_ekle_Click(object sender, EventArgs e)
{
for (int k=clb_input.Items.Count-1; k >= 0; k--)
{
if (clb_input.GetItemChecked(k) == true)
{
q.Add(clb_input.Items[k].ToString());
clb_input.Items.RemoveAt(k);
}
else { }
}
q.Sort((p1,p2)=>((int)(p1.split(" ")[1])).CompareTo((int)(p2.split(" ")[1])));
for (int t = 0; t < q.Count; t++)
{
clb_output.Items.Add(q[t].ToString());
}
}

Number of loop recursions as a parameter

I'm building a list of strings that contains all permutations of 2-letter strings, for instance "aa" to "zz". This is what I have:
public List<string> SomeMethod(int NumberOfChars) {
for (var i = 0; i < 26; i++)
{
char character1 = (char)(i + 97);
var Letter1 = character1.ToString();
for (var j = 0; j < 26; j++)
{
char character2 = (char)(j + 97);
var Letter2 = character2.ToString();
string TheString = Letter1 + Letter2;
TheList.Add(TheString);
}
}
return TheList;
}
Basically, it's a loop inside a loop that combines characters from the alphabet. Now suppose I want to include NumberOfChars as a parameter that determines the length of each string. For instance, if I pass in 2 it would return all 676 2-letter strings from "aa" to "zz" and if I pass in 3 it would return all 17,576 3-letter strings from "aaa" to "zzz".
For the moment, the easiest way to do it would be to have two different methods, one that returns 2-letter strings with two nested loops and another one that returns 3-letter strings with 3 nested loops.
What's a cleaner way to do this?
Thanks.
How about a method like this:
public IEnumerable<string> SomeMethod(int NumberOfChars)
{
if (NumberOfChars == 0)
{
yield return string.Empty;
}
else
{
for (var i = 'a'; i <= 'z'; i++)
{
foreach (var s in SomeMethod(NumberOfChars - 1))
{
yield return i + s;
}
}
}
}
And just for fun, here's another solution using Linq:
public IEnumerable<string> SomeMethod(int n)
{
var r = Enumerable.Range('a', 26).Select(x => ((char)x).ToString());
return (n > 1) ? r.SelectMany(x => SomeMethod(n - 1), (x, y) => x + y) : r;
}
Here's an alternative that uses a loop instead of recursion:
public static List<string> SomeMethod(int numberOfChars)
{
IEnumerable<string> results = new List<string> { "" };
for (int i = 0; i < numberOfChars; ++i)
results = from s in results
from c in Enumerable.Range('a', 26)
select s + (char)c;
return results.ToList();
}

Counting how many times a certain char appears in a string before any other char appears

I have many strings. Each string is prepended with at least 1 $. What is the best way to loop through the chars of each string to count how many $'s there are per string.
eg:
"$hello" - 1
"$$hello" - 2
"$$h$ello" - 2
You could use the Count method
var count = mystring.Count(x => x == '$')
int count = myString.TakeWhile(c => c == '$').Count();
And without LINQ
int count = 0;
while(count < myString.Length && myString[count] == '$') count++;
The simplest approach would be to use LINQ:
var count = text.TakeWhile(c => c == '$').Count();
There are certainly more efficient approaches, but that's probably the simplest.
You could do this, it doesn't require LINQ, but it's not the best way to do it(since you make split the whole string and put it in an array and just pick the length of it, you could better just do a while loop and check every character), but it works.
int count = test.Split('$').Length - 1;
var str ="hello";
str.Where(c => c == 'l').Count() // 2
int count = yourText.Length - yourText.TrimStart('$').Length;
int count = Regex.Matches(myString,"$").Count;
public static int GetHowManyTimeOccurenceCharInString(string text, char c)
{
int count = 0;
foreach(char ch in text)
{
if(ch.Equals(c))
{
count++;
}
}
return count;
}
just a simple answer:
public static int CountChars(string myString, char myChar)
{
int count = 0;
for (int i = 0; i < myString.Length; i++)
{
if (myString[i] == myChar) ++count;
}
return count;
}
Cheers! - Rick
One approach you could take is the following method:
// Counts how many of a certain character occurs in the given string
public static int CharCountInString(char chr, string str)
{
return str.Split(chr).Length-1;
}
As per the parameters this method returns the count of a specific character within a specific string.
This method works by splitting the string into an array by the specified character and then returning the length of that array -1.
//This code worked for me
class CountOfLettersOfString
{
static void Main()
{
Console.WriteLine("Enter string to check count of letters");
string name = Console.ReadLine();
//Method1
char[] testedalphabets = new char[26];
int[] letterCount = new int[26];
int countTestesd = 0;
Console.WriteLine($"Given String is:{name}");
for (int i = 0; i < name.Length - 1; i++)
{
int countChar = 1;
bool isCharTested = false;
for (int j = 0; j < testedalphabets.Length - 1; j++)
{
if (name[i] == testedalphabets[j])
{
isCharTested = true;
break;
}
}
if (!isCharTested)
{
testedalphabets[countTestesd] = name[i];
for (int k = i + 1; k < name.Length - 1; k++)
{
if (name[i] == name[k])
{
countChar++;
}
}
letterCount[countTestesd] = countChar;
countTestesd++;
}
else
{
continue;
}
}
for (int i = 0; i < testedalphabets.Length - 1; i++)
{
if (!char.IsLetter(testedalphabets[i]))
{
continue;
}
Console.WriteLine($"{testedalphabets[i]}-{letterCount[i]}");
}
//Method2
var g = from c in name.ToLower().ToCharArray() // make sure that L and l are the same eg
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in g)
{
Console.WriteLine(string.Format("Character:{0} Appears {1} times", item.Key.ToString(), item.Count));
}
Console.ReadLine();
}
}
This is a similar Solution to find how many email addresses included in a string. This way is more efficient`
int count = 0;
foreach (char c in email.Trim())
if (c == '#') count++;

Categories