Find and Count works but not the way I want - c#

byte count = 0;
string word = "muumuu";
string res= word;
bool flg = true;
foreach(char ch in word)
{
res = res.Remove(0,1);
if(res.Contains(ch))
{
flg = false;
count ++;
Console.WriteLine($"there are {count} same chars : {ch}");
}
}
if(flg)
{
Console.WriteLine($"All chars are different in : {word} ");
}
The output is :
there are 1 same chars : m
there are 2 same chars : u
there are 3 same chars : u
there are 4 same chars : u
The question is how to count same chars like :
there are 2 same chars : m
there are 4 same chars : u

You have to separate the counting from the output of the result.
The following solution collects the character counts in a dictionary and after that displays the contents of the dictionary:
string word = "muumuu";
var counts = new Dictionary<char, int>();
foreach (var ch in word)
{
if (counts.ContainsKey(ch))
counts[ch]++;
else
counts[ch] = 1;
}
foreach (var chCount in counts)
{
Console.WriteLine($"{chCount.Value} occurrences of '{chCount.Key}'");
}
A very compact alternative solution using Linq GroupBy method:
string word = "muumuu";
foreach (var group in word.GroupBy(c => c))
{
Console.WriteLine($"{group.Count()} occurrences of '{group.Key}'");
}
GroupBy groups the characters in the word so that each distinct character creates a group and each group contains the collected identical characaters. These can then be counted using Count.
Result:
2 occurrences of 'm'
4 occurrences of 'u'

Klaus' answer might be easier to understand, but you can also use this function which does mostly the same thing:
public static int CountDuplicates(string str) =>
(from c in str.ToLower()
group c by c
into grp
where grp.Count() > 1
select grp.Key).Count();
Usage: var dupes = $"{word} - Duplicates: {CountDuplicates(word)}";

Related

How to detect the 3rd, 4th, 5th letter in a string C#

I have a string structured like:
string s = "0R 0R 20.0V 100.0V 400.0R 60R 70.0R";
My question is, how would I detect only the 3rd, 4th, 5th letter through if statements like so:
3rd letter = V
4th letter = V
5th letter = R
//pseudocode below
if (3rd letter in string == V)
{
return true;
}
if (4th letter in string == V)
{
return true;
}
if (5th letter in string == R)
{
return true;
}
or through print statements:
3rd letter = V
4th letter = V
5th letter = R
// Pseudocode below:
Console.WriteLine("3rd Letter"); //should return V
Console.WriteLine("4th Letter"); //should return V
Console.WriteLine("5th Letter"); //should return R
I was thinking of using a foreach loop to loop through the string but I am unsure how to detect when it is the 3rd, 4th, 5th letter, I know that regex may help but I'm not sure how to implement the expression
string s = "0R 0R 20.0V 100.0V 400.0R 60R 70.0R";
foreach(char c in s)
{
// detect 3rd 4th 5th letter in here
}
First, let's extract / match letters either with a help of Linq:
using System.Linq;
...
string[] letters = s
.Where(c => c >= 'A' && c <= 'Z')
.Select(c => c.ToString())
.ToArray();
or regular expressions:
using System.Linq;
using System.Text.RegularExpressions;
...
string[] letters = Regex
.Matches(s, "[A-Z]")
.Cast<Match>()
.Select(m => m.Value)
.ToArray();
Then you can put as easy as
string letter3d = letters[3 - 1]; // - 1 : arrays are zero based
string letter4th = letters[4 - 1];
string letter5th = letters[5 - 1];

How to count 2 or 3 letter words in a string using asp c#

How to count 2 or 3 letter words of a string using asp csharp, eg.
string value="This is my string value";
and output should look like this
2 letter words = 2
3 letter words = 0
4 letter words = 1
Please help, Thanks in advance.
You can try something like this:
split sentence by space to get array of words
group them by length of word (and order by that length)
iterate through every group and write letter count and number of words with that letter count
code
using System.Linq;
using System.Diagnostics;
...
var words = value.Split(' ');
var groupedByLength = words.GroupBy(w => w.Length).OrderBy(x => x.Key);
foreach (var grp in groupedByLength)
{
Debug.WriteLine(string.Format("{0} letter words: {1}", grp.Key, grp.Count()));
}
First of all you need to decide what counts as a word. A naive approach is to split the string with spaces, but this will also count commas. Another approach is to use the following regex
\b\w+?\b
and collect all the matches.
Now you got all the words in a words array, we can write a LINQ query:
var query = words.Where(x => x.Length >= 2 && x.Length <= 4)
.GroupBy(x => x.Length)
.Select(x => new { CharCount = x.Key, WordCount = x.Count() });
Then you can print the query out like this:
query.ToList().ForEach(Console.WriteLine);
This prints:
{ CharCount = 4, WordCount = 1 }
{ CharCount = 2, WordCount = 2 }
You can write some code yourself to produce a more formatted output.
If i understood your question correctly
You can do it using dictionary
First split the string by space in this case
string value = "This is my string value";
string[] words = value.Split(' ');
Then loop trough array of words and set the length of each word as a key of dictionary, note that I've used string as a key, but you can modify this to your needs.
Dictionary<string, int> latteWords = new Dictionary<string,int>();
for(int i=0;i<words.Length;i++)
{
string key = words[i].Length + " letter word";
if (latteWords.ContainsKey(key))
latteWords[key] += 1;
else
latteWords.Add(key, 1);
}
And the output would be
foreach(var ind in latteWords)
{
Console.WriteLine(ind.Key + " = " + ind.Value);
}
Modify this by wish.

How to ignore the punctuation c#

I want to ignore the punctuation.So, I'm trying to make a program that counts all the appearences of every word in my text but without taking in consideration the punctuation marks.
So my program is:
static void Main(string[] args)
{
string text = "This my world. World, world,THIS WORLD ! Is this - the world .";
IDictionary<string, int> wordsCount =
new SortedDictionary<string, int>();
text=text.ToLower();
text = text.replaceAll("[^0-9a-zA-Z\text]", "X");
string[] words = text.Split(' ',',','-','!','.');
foreach (string word in words)
{
int count = 1;
if (wordsCount.ContainsKey(word))
count = wordsCount[word] + 1;
wordsCount[word] = count;
}
var items = from pair in wordsCount
orderby pair.Value ascending
select pair;
foreach (var p in items)
{
Console.WriteLine("{0} -> {1}", p.Key, p.Value);
}
}
The output is:
is->1
my->1
the->1
this->3
world->5
(here is nothing) -> 8
How can I remove the punctuation here?
You should try specifying StringSplitOptions.RemoveEmptyEntries:
string[] words = text.Split(" ,-!.".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
Note that instead of manually creating a char[] with all the punctuation characters, you may create a string and call ToCharArray() to get the array of characters.
I find it easier to read and to modify later on.
string[] words = text.Split(new char[]{' ',',','-','!','.'}, StringSplitOPtions.RemoveEmptyItems);
It is simple - first step is to remove undesired punctuation with function Replace and then continue with splitting as you have it.
... you can go with the making people cry version ...
"This my world. World, world,THIS WORLD ! Is this - the world ."
.ToLower()
.Split(" ,-!.".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.GroupBy(i => i)
.Select(i=>new{Word=i.Key, Count = i.Count()})
.OrderBy(k => k.Count)
.ToList()
.ForEach(Console.WriteLine);
.. output
{ Word = my, Count = 1 }
{ Word = is, Count = 1 }
{ Word = the, Count = 1 }
{ Word = this, Count = 3 }
{ Word = world, Count = 5 }

How to find maximum number of repeated string in a string in a list of string in c#

If we have a list of strings, then how we can find the list of strings that have the maximum number of repeated symbol by using LINQ.
List <string> mylist=new List <string>();
mylist.Add("%1");
mylist.Add("%136%250%3"); //s0
mylist.Add("%1%5%20%1%10%50%8%3"); // s1
mylist.Add("%4%255%20%1%14%50%8%4"); // s2
string symbol="%";
List <string> List_has_MAX_num_of_symbol= mylist.OrderByDescending(s => s.Length ==max_num_of(symbol)).ToList();
//the result should be a list of s1 + s2 since they have **8** repeated '%'
I tried
var longest = mylist.Where(s => s.Length == mylist.Max(m => m.Length)) ;
this gives me only one string not both
Here's a very simple solution, but not exactly efficient. Every element has the Count operation performed twice...
List<string> mylist = new List<string>();
mylist.Add("%1");
mylist.Add("%136%250%3"); //s0
mylist.Add("%1%5%20%1%10%50%8%3"); // s1
mylist.Add("%4%255%20%1%14%50%8%4"); // s2
char symbol = '%';
var maxRepeat = mylist.Max(item => item.Count(c => c == symbol));
var longest = mylist.Where(item => item.Count(c => c == symbol) == maxRepeat);
It will return 2 strings:
"%1%5%20%1%10%50%8%3"
"%4%255%20%1%14%50%8%4"
Here is an implementation that depends upon SortedDictionary<,> to get what you're after.
var mylist = new List<string> {"%1", "%136%250%3", "%1%5%20%1%10%50%8%3", "%4%255%20%1%14%50%8%4"};
var mappedValues = new SortedDictionary<int, IList<string>>();
mylist.ForEach(str =>
{
var count = str.Count(c => c == '%');
if (mappedValues.ContainsKey(count))
{
mappedValues[count].Add(str);
}
else
{
mappedValues[count] = new List<string> { str };
}
});
// output to validate output
foreach (var str in mappedValues.Last().Value)
{
Console.WriteLine(str);
}
Here's one using LINQ that gets the result you're after.
var result = (from str in mylist
group str by str.Count(c => c == '%')
into g
let max = (from gKey in g select g.Key).Max()
select new
{
Count = max,
List = (from str2 in g select str2)
}).LastOrDefault();
OK, here's my answer:
char symbol = '%';
var recs = mylist.Select(s => new { Str = s, Count = s.Count(c => c == symbol) });
var maxCount = recs.Max(x => x.Count);
var longest = recs.Where(x => x.Count == maxCount).Select(x => x.Str).ToList();
It is complicated because it has three lines (the char symbol = '%'; line excluded), but it counts each string only once. EZI's answer has only two lines, but it is complicated because it counts each string twice. If you really want a one-liner, here it is:
var longest = mylist.Where(x => x.Count(c => c == symbol) == mylist.Max(y => y.Count(c => c == symbol))).ToList();
but it counts each string many times. You can choose whatever complexity you want.
We can't assume that the % is always going to be the most repeated character in your list. First, we have to determine what character appears the most in an individual string for each string.
Once we have the character and it maximum occurrence, we can apply Linq to the List<string> and grab the strings that contain the character equal to its max occurrence.
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
List <string> mylist=new List <string>();
mylist.Add("%1");
mylist.Add("%136%250%3");
mylist.Add("%1%5%20%1%10%50%8%3");
mylist.Add("%4%255%20%1%14%50%8%4");
// Determine what character appears most in a single string in the list
char maxCharacter = ' ';
int maxCount = 0;
foreach (string item in mylist)
{
// Get the max occurrence of each character
int max = item.Max(m => item.Count(c => c == m));
if (max > maxCount)
{
maxCount = max;
// Store the character whose occurrence equals the max
maxCharacter = item.Select(c => c).Where(c => item.Count(i => i == c) == max).First();
}
}
// Print the strings containing the max character
mylist.Where(item => item.Count(c => c == maxCharacter) == maxCount)
.ToList().ForEach(Console.WriteLine);
}
}
Results:
%1%5%20%1%10%50%8%3
%4%255%20%1%14%50%8%4
Fiddle Demo
var newList = myList.maxBy(x=>x.Count(y=>y.Equals('%'))).ToList();
This should work. Please correct syntax if wrong anywhere and update here too if it works for you.

Numbering - algorithm in a 2d array - "assign occurrence of a letter" - in c#

I need to create an algorithm in C# that basically counts the occurrence of a letter in the first column of an array and writes it into the 2nd column, for example:
a | 1
a | 2
b | 1
c | 1
a | 3
b | 2
b | 3
c | 2 (...)
I feel like using LINQ would do the trick, but for now I cannot think of the correct way.
Two separate 1d arrays would do fine, too, as long as the indices match.
Thanks for hints and thoughts!
You cannot mix types in a multi dimensional arrays. You could use Dictionary<char,int> instead where the key is the letter and the value is the occurence. However, that would not be the same as your char[] where letters can repeat.
So here is an approach than is more maintainable and readable using a custom struct with all relevant properties.
public struct LetterInfo
{
public char Letter { get; set; }
public int Occurence { get; set; }
public int Index { get; set; }
public override string ToString()
{
return string.Format("{0}:{1}->{2}", Index, Letter, Occurence);
}
}
Given that you have already a char[] and you want to have all missing informations you could get them with LINQ in this way:
char[] letters = {'a', 'a' , 'b', 'c', 'a', 'b', 'b', 'c'};
LetterInfo[] letterInfos = letters
.Select((c, i) => new { Letter = c, Index = i })
.GroupBy(x => x.Letter)
.SelectMany(xGrp => xGrp
.Select((x, i) => new LetterInfo
{
Letter = x.Letter, Occurence = i + 1,
Index = x.Index
}))
.OrderBy(li => li.Index)
.ToArray();
string output = string.Join(Environment.NewLine, letterInfos);
Console.Write(output);
Output:
0:a->1
1:a->2
2:b->1
3:c->1
4:a->3
5:b->2
6:b->3
7:c->2
Here's an approach without LINQ that should be more efficient but more memory-hungry (you can use List<LetterInfo> alone instead of the array to avoid another collection):
var latterList = new List<LetterInfo>();
var dict = new Dictionary<char, int>();
for (int i = 0; i < letters.Length; i++)
{
char c = letters[i];
int occ = 0;
dict.TryGetValue(c, out occ);
dict[c] = ++occ;
var li = new LetterInfo { Letter = c, Index = i, Occurence = occ };
latterList.Add(li);
}
letterInfos = latterList.ToArray();
For the sake of completeness, here's the dictionary approach mentioned above to lookup a char and it's occurence:
Dictionary<char, int> letterCount = letters
.GroupBy(l => l)
.ToDictionary(g => g.Key, g => g.Count());
If you want to know how often the letter a is in the array:
int aCount = letterCount['a']; // throws an exception if a is not in the dictionary
or safer:
int aCount = 0;
bool contains = letterCount.TryGetValue('a', out aCount);
So you would need a dictionary to keep track of your letters.
Dictionary<char, int> CharacterTracker
if we have
char[] characters
int[] occurrences
Then I would just iterate through characters. If we don't have that character in our Dictionary, then we put '1' in the corresponding occurences array, and character as a key in the Dictionary and 1 as its value. If we do have that character in our Dictionary, increment the value for the Dictionary[character], and put that value in occurences
This might be one of the cases where LINQ offers little benefit.
var letters = "aabcabbc";
var dict = new Dictionary<char, int>();
var counts = letters.Select(letter =>
{
int count;
dict.TryGetValue(letter, out count); // defaults to 0 if not found
dict[letter] = ++count;
return new { Letter = letter, Count = count };
});
Obligatory attempt in Linq (note: not a recommended solution!). It's getting the result as an IEnumerable<Tuple<char, int>>...
char[] chars = "aabcabbc".ToCharArray();
var result = Enumerable.Range(0, chars.Length).Select(i => new Tuple<char, int>(chars[i], chars.Take(i + 1).Count(c => c == chars[i])));
Why using hammers to smash flies ? Use an array of counters indexed by letters. A dictionary brings no benefit here. And LINQ is a big sledgehammer.
Pseudocode:
: Initialize
for c in "a..z"
counter[c]= 0
: Count
for c in string
counter[c]++

Categories

Resources