I want to count how many numbers (only 0,1,2,3) and letters (a,b,c,d) were used in a line that I'm checking - they are mixed, for example: 3b1c1c1a1a0b1a1d3d0a3c. How can I count that?
int numbers = 0;
int letters = 0;
foreach(char a in myString)
{
if (Char.IsDigit(a))
numbers ++;
else if (Char.IsLetter(a)){
letters ++;
}
You could also use predefined Linq expressions if these need to be re-used:
var characterList = "234234abce".ToCharArray();
var validCharacters = "0123abcd".ToCharArray();
Func<char, bool> ValidLetter = delegate(char c){
return Char.IsLetter(c) && validCharacters.Contains(c);
};
Func<char, bool> ValidNumber = delegate(char c){
return Char.IsDigit(c) && validCharacters.Contains(c);
};
var letterCount = characterList.Where(c => ValidLetter(c)).Count();
var numberCount = characterList.Where(c => ValidNumber(c)).Count();
You can use the ASCII code to get it work
for(int i = 0 ; i < str.Length ; i++){
int asciicode = (int)str[i];
if(asciicode >= 48 && asciicode <= 57)
number++;
else
alphabet++;
}
This is an example to find the count of character "1":
string input = "3b1c1c1a1a0b1a1d3d0a3c";
int count = input.ToArray().Count(i => i == '1');
There's a method for doing that:
int count = myString.ToCharArray().Where(c => Char.IsLetterOrDigit(c)).Count();
If you want to split them out then:
int letterCount = myString.ToCharArray().Where(c => Char.IsLetter(c)).Count();
int numberCount = myString.ToCharArray().Where(c => Char.IsDigit(c)).Count();
If you want to filter them based on the numbers:
List<char> searchFor = new List<char>() { '0', '1', '2', '3' };
int numberCount = myString.ToCharArray().Where(c => searchFor.Contains(c)).Count();
Below meets your requirements:
string acceptedChars = "0123abcd";
var res = "3b1c1c1a1a0b1a1d3d0a3c".ToCharArray()
.Where(x => acceptedChars.Contains(x))
.GroupBy(x => char.IsDigit(x))
.Select(g => new{ isDigit = g.Key, count = g.Count() } );
var digitsCount = res.Single(r => r.isDigit == true).count;
var lettersCount = res.Single(r => r.isDigit == false).count;
Related
I have an array list. Which contains month number and data as comma separated.
Now I want to loop through this list and check if any month number is missing. If then need to add that month number in order with data part as zero.
List<string> MyData = new List<string>();
MyData.Add("4,500"); //dynamically adding. 4(april) and 6(june) are month numbers.
MyData.Add("6,400");
foreach (string str in MyData)
{
int GetmonthNum = Convert.ToInt32(str.Substring(0, str.IndexOf(',')));
}
Now need to add all other missing month number with value as zero. The resulted List should be
"4,500","5,0","6,400","7,0","8,0","9,0","10,0","11,0","12,0","1,0","2,0","3,0"
You could use contains like this
var result = new List<string>();
for (int i = 1; i <= 12 ; i++)
{
var firstMatch = myData.FirstOrDefault(x => x.Contains(i + ","));
if (firstMatch == null)
{
result.Add(i + ",0");
}
else
{
result.Add(firstMatch);
}
// or short code: result.Add(firstMatch ?? i + ",0" );
}
If you want "4,500" is the first item then try it
var minMonth = myData.Min(x => Convert.ToInt32(x.Substring(0, x.IndexOf(",", StringComparison.CurrentCulture))));
var result = new List<string>();
for (int i = minMonth - 1; i < minMonth + 11; i++)
{
var firstMatch = myData.FirstOrDefault(x => x.StartsWith((i % 12) + 1 + ","));
result.Add(firstMatch ?? (i % 12) + 1 + ",0");
}
In case if there are 12 item in your list [respective to 12 month] try below code
List<string> MyData = new List<string>();
MyData.Add("4,500"); //dynamically adding. 4(april) and 6(june) are month numbers.
MyData.Add("6,400");
int i = 1;
// use variable i from 1 to 12 as month indicator
foreach (string str in MyData)
{
string month = str.Substring(0, str.IndexOf(','));
// get the month from your list item here
int GetmonthNum = Convert.ToInt32( month==string.Empty || month==null ? i.ToString() : month );
// here use conditional operator to check if month is not there in list item , if it is not present than return i as misisng month
i++;
}
Let me know if you feel any problem in putting the code together
List<string> MyData = new List<string>();
MyData.Add("4,500");
MyData.Add("6,400");
var months = Enumerable.Range(1, 12);
foreach (int month in months)
{
if (MyData.Any(a => a.Split(',')[0] == month.ToString()))
continue;
MyData.Add(string.Format("{0},{1}", month.ToString(), "0"));
}
This works:
MyData =
MyData
.Select(x => x.Split(',').Select(y => int.Parse(y)).ToArray())
.Concat(Enumerable.Range(1, 12).Select(x => new [] { x, 0 }).ToArray())
.OrderBy(x => x[0])
.GroupBy(x => x[0], x => x[1])
.SelectMany(x => x.Take(1), (y, z) => $"{y.Key},{z}")
.ToList();
And that gives:
1,0
2,0
3,0
4,500
5,0
6,400
7,0
8,0
9,0
10,0
11,0
12,0
I was able to achieve your desired result with the following loop. There are many ways to do it though.
int arrayIndex = 0;
int month = 1;
for (int i = 0; i < 12; i++)
{
if (myArray[arrayIndex].Split(',')[0] == Convert.ToString(month))
{
MyData.Add(myArray[arrayIndex]);
month++;
arrayIndex++;
}
else
{
MyData.Add(Convert.ToString(month) + ",0");
month++;
}
}
sort array in that manner that sorted array's member starts in ascending order but o value comes at last in c#
ulong[] arr = new ulong[30];
arr[0]=13325647855656;
arr[1]=65897426666332;
arr[2]=00685956265661;
arr[4]=0;
then output must be
arr[0]=00685956265661;
arr[1]=13325647855656;
arr[2]=65897426666332;
arr[4]=0;
you can use Linq OrderBy and ThenBy
ulong[] arr = new ulong[30];
arr[0] = 13325647855656;
arr[1] = 65897426666332;
arr[2] = 00685956265661;
arr[4] = 0;
var results = arr.OrderBy(x => x == 0).ThenBy(x => x);
You can use Array.Sort with this custom comparison delegate:
Array.Sort(arr, (u1, u2) =>
{
if (u1 == 0 && u2 == 0) return 0;
else if (u1 == 0) return ulong.MaxValue.CompareTo(u2);
else if (u2 == 0) return u1.CompareTo(ulong.MaxValue);
else return u1.CompareTo(u2);
});
Demo
If you want to use Linq (ToArray() needs to create an additonal array internally), i would use:
arr = arr.OrderBy(x => x == 0).ThenBy(x => x).ToArray();
class ZeroIsBigComparer : System.Collections.Generic.IComparer<ulong>
{
public int Compare(ulong x, ulong y)
{
if (x == y) return 0;
if (x == 0) return 1;
if (y == 0) return -1;
return x.CompareTo(y);
}
}
then
var comparer = new ZeroIsBigComparer();
arr = arr.OrderBy(x => x, comparer).ToArray();
I'm reading in a text file using StreamReader to the program. I need to record the frequency of each letter in the string into an array (where index 0 would be A, and so on). What's the simplest approach for this?
Edit: I had this originally, until I realized it was completely wrong.
int counter = 0;
int[] freq = new int[26]; // create frequency array
// counts frequency
while (counter < inValue.Length)
{
int A = 65; // ASCII value for "A"
char x = char.Parse(inValue.Substring(counter, 1)); // get individual characters from string
int s = (int)x; // cast character to integer value
if (s == A + counter)
freq[counter]++;
counter++;
}
Where inValue is the text file StreamReader reads into the program.
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.ToDictionary(g => g.Key, g => g.Count());
This should give you a Dictionary of characters and their count.
Update:
If you want case insensitive counts, just change the GroupBy:
.GroupBy(c => Char.ToUpper(c)) // instead of .GroupBy(c => c)
And in my opinion a dictionary is better than an array in this case because the character that the "count" belongs to is not just implied by the index; instead, it is an explicit key. This makes lookups easier because you don't have to convert the character to an index. Additionally, this makes it more flexible when adding internationalization support. However, if you absolutely need an array, it is a simple change:
var freqs = File.ReadAllText("myfile.txt")
.Where(c => Char.IsLetter(c))
.GroupBy(c => c)
.OrderBy(g => g.Key)
.Select(g => g.Count())
.ToArray()
You can try something like this. This worked for me but I didnt used StreamReader:-
int[] c = new int[(int)char.MaxValue];
string s = File.ReadAllText("text.txt");
foreach (char t in s)
{
c[(int)t]++;
}
for (int i = 0; i < (int)char.MaxValue; i++)
{
if (c[i] > 0 &&
char.IsLetterOrDigit((char)i))
{
Console.WriteLine("Letter: {0} Frequency: {1}",(char)i, c[i]);
}
}
A few modifications to your code will make it work, assuming that you only want to count the letters 'A' through 'Z':
int counter = 0;
int[] freq = new int[26]; // create frequency array
// counts frequency
while (counter < inValue.Length)
{
char c = invalue[counter];
if (c >= 'A' && c <= 'Z')
{
++freq[(int)c - 65]
}
++counter;
}
If you want to count lower case letters as well, then change the first line in the loop to:
char c = char.ToUpper(invalue[counter]);
I spent quite a while to figure out this Linq which will result in the exact same array you want:
int[] occurance = File.ReadAllText("myfile.txt")
.Where(c => char.IsLetter(c))
.Select(c => (int)char.ToUpperInvariant(c) - 65)
.GroupBy(a => a)
.ToDictionary(a => a.Key, a => a.Count())
.OrderBy(a => a.Key)
.Select(a => a.Value)
.ToArray();
I wanted to split a string
Input :
ABCDEFGHI
Output :
ABC, DEF, GHI
One way is by using For Loop.
string str = "ABCDEFGHI";
List<string> lst = new List<string>();
string temp = "";
for(int i = 0; i < str.Length; i++)
{
temp = str[i].Tostring();
if((i + 1) % 3 == 0)
{
lst.Add(temp);
temp = "";
}
}
string final_str = string.Join(", ", lst);
But how to do that using LINQ?
And another one (without MoreLinq):
var str = "ABCDEFGHI";
var tmp = str.Select((i, index) => new { i, index })
.GroupBy(g => g.index / 3, e => e.i)
.Select(g => String.Join("", g));
var final_string = String.Join(", ", tmp);
With the help of MoreLinq
List<string> lst = str.Batch(3).Select(s => String.Join("",s)).ToList();
using MoreLinq.Batch
var result = str.Batch(3);
type of result is IEnumerable>, ToArray can be used to make it IEnumerable< char[] >
EDIT I forgot last join statement in the first glance
var finalStr = String.Join(",",str.Batch(3).Select(x=>new String(x.ToArray())))
var str = "ABCDEFGHI";
var result = testStr.Select(s => testStr.IndexOf(s))
.Where(i => i%3 == 0)
.Select(i => testStr.Substring(i,3))
.Aggregate("", (a,s) => a += s + ",");
String.Join("", str.Select((x, i) => (i + 1)%3 == 0 ? x + " " : x.ToString()))
This question already has answers here:
C# LINQ find duplicates in List
(13 answers)
Closed 3 years ago.
I have a List<string> which has some words duplicated. I need to find all words which are duplicates.
Any trick to get them all?
In .NET framework 3.5 and above you can use Enumerable.GroupBy which returns an enumerable of enumerables of duplicate keys, and then filter out any of the enumerables that have a Count of <=1, then select their keys to get back down to a single enumerable:
var duplicateKeys = list.GroupBy(x => x)
.Where(group => group.Count() > 1)
.Select(group => group.Key);
If you are using LINQ, you can use the following query:
var duplicateItems = from x in list
group x by x into grouped
where grouped.Count() > 1
select grouped.Key;
or, if you prefer it without the syntactic sugar:
var duplicateItems = list.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key);
This groups all elements that are the same, and then filters to only those groups with more than one element. Finally it selects just the key from those groups as you don't need the count.
If you're prefer not to use LINQ, you can use this extension method:
public void SomeMethod {
var duplicateItems = list.GetDuplicates();
…
}
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> source) {
HashSet<T> itemsSeen = new HashSet<T>();
HashSet<T> itemsYielded = new HashSet<T>();
foreach (T item in source) {
if (!itemsSeen.Add(item)) {
if (itemsYielded.Add(item)) {
yield return item;
}
}
}
}
This keeps track of items it has seen and yielded. If it hasn't seen an item before, it adds it to the list of seen items, otherwise it ignores it. If it hasn't yielded an item before, it yields it, otherwise it ignores it.
and without the LINQ:
string[] ss = {"1","1","1"};
var myList = new List<string>();
var duplicates = new List<string>();
foreach (var s in ss)
{
if (!myList.Contains(s))
myList.Add(s);
else
duplicates.Add(s);
}
// show list without duplicates
foreach (var s in myList)
Console.WriteLine(s);
// show duplicates list
foreach (var s in duplicates)
Console.WriteLine(s);
If you're looking for a more generic method:
public static List<U> FindDuplicates<T, U>(this List<T> list, Func<T, U> keySelector)
{
return list.GroupBy(keySelector)
.Where(group => group.Count() > 1)
.Select(group => group.Key).ToList();
}
EDIT: Here's an example:
public class Person {
public string Name {get;set;}
public int Age {get;set;}
}
List<Person> list = new List<Person>() { new Person() { Name = "John", Age = 22 }, new Person() { Name = "John", Age = 30 }, new Person() { Name = "Jack", Age = 30 } };
var duplicateNames = list.FindDuplicates(p => p.Name);
var duplicateAges = list.FindDuplicates(p => p.Age);
foreach(var dupName in duplicateNames) {
Console.WriteLine(dupName); // Will print out John
}
foreach(var dupAge in duplicateAges) {
Console.WriteLine(dupAge); // Will print out 30
}
Using LINQ, ofcourse.
The below code would give you dictionary of item as string, and the count of each item in your sourc list.
var item2ItemCount = list.GroupBy(item => item).ToDictionary(x=>x.Key,x=>x.Count());
For what it's worth, here is my way:
List<string> list = new List<string>(new string[] { "cat", "Dog", "parrot", "dog", "parrot", "goat", "parrot", "horse", "goat" });
Dictionary<string, int> wordCount = new Dictionary<string, int>();
//count them all:
list.ForEach(word =>
{
string key = word.ToLower();
if (!wordCount.ContainsKey(key))
wordCount.Add(key, 0);
wordCount[key]++;
});
//remove words appearing only once:
wordCount.Keys.ToList().FindAll(word => wordCount[word] == 1).ForEach(key => wordCount.Remove(key));
Console.WriteLine(string.Format("Found {0} duplicates in the list:", wordCount.Count));
wordCount.Keys.ToList().ForEach(key => Console.WriteLine(string.Format("{0} appears {1} times", key, wordCount[key])));
I'm assuming each string in your list contains several words, let me know if that's incorrect.
List<string> list = File.RealAllLines("foobar.txt").ToList();
var words = from line in list
from word in line.Split(new[] { ' ', ';', ',', '.', ':', '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
select word;
var duplicateWords = from w in words
group w by w.ToLower() into g
where g.Count() > 1
select new
{
Word = g.Key,
Count = g.Count()
}
I use a method like that to check duplicated entrys in a string:
public static IEnumerable<string> CheckForDuplicated(IEnumerable<string> listString)
{
List<string> duplicateKeys = new List<string>();
List<string> notDuplicateKeys = new List<string>();
foreach (var text in listString)
{
if (notDuplicateKeys.Contains(text))
{
duplicateKeys.Add(text);
}
else
{
notDuplicateKeys.Add(text);
}
}
return duplicateKeys;
}
Maybe it's not the most shorted or elegant way, but I think that is very readable.
lblrepeated.Text = "";
string value = txtInput.Text;
char[] arr = value.ToCharArray();
char[] crr=new char[1];
int count1 = 0;
for (int i = 0; i < arr.Length; i++)
{
int count = 0;
char letter=arr[i];
for (int j = 0; j < arr.Length; j++)
{
char letter3 = arr[j];
if (letter == letter3)
{
count++;
}
}
if (count1 < count)
{
Array.Resize<char>(ref crr,0);
int count2 = 0;
for(int l = 0;l < crr.Length;l++)
{
if (crr[l] == letter)
count2++;
}
if (count2 == 0)
{
Array.Resize<char>(ref crr, crr.Length + 1);
crr[crr.Length-1] = letter;
}
count1 = count;
}
else if (count1 == count)
{
int count2 = 0;
for (int l = 0; l < crr.Length; l++)
{
if (crr[l] == letter)
count2++;
}
if (count2 == 0)
{
Array.Resize<char>(ref crr, crr.Length + 1);
crr[crr.Length - 1] = letter;
}
count1 = count;
}
}
for (int k = 0; k < crr.Length; k++)
lblrepeated.Text = lblrepeated.Text + crr[k] + count1.ToString();