How to get the element of array with Max Value? - c#

I'm trying to get the letter of an array that as a max value of a repeated letters on a string.
I have is this:
var AsciiCode = new int[255];
string word= "Hello everybody";
foreach (char c in word)
{
AsciiCode[c]++;
}
MessageBox.Show(string.Format("The max count is:
{0}\nLetter: {1}", AsciiCode.Max(), AsciiCode.ElementAt(//MAX_VALUE_HERE//) ));

A solution with using Linq can be this:
var res =
word.GroupBy(g => g)
.Select(c => new { c.Key, Count = c.Count() })
.OrderByDescending(o => o.Count)
.FirstOrDefault();
C# Demo

Related

How to find the duplicates in the given string in c#

I want to find the duplicates for a given string, I tried for collections, It is working fine, but i don't know how to do it for a string.
Here is the code I tried for collections,
string name = "this is a a program program";
string[] arr = name.Split(' ');
var myList = new List<string>();
var duplicates = new List<string>();
foreach(string res in arr)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else
{
duplicates.Add(res);
}
}
foreach(string result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
But I want to find the duplicates for the below string and to store it in an array. How to do that?
eg:- string aa = "elements";
In the above string i want to find the duplicate characters and store it in an array
Can anyone help me?
Linq solution:
string name = "this is a a program program";
String[] result = name.Split(' ')
.GroupBy(word => word)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
Console.Write(String.Join(Environment.NewLine, result));
The same princicple for duplicate characters within a string:
String source = "elements";
Char[] result = source
.GroupBy(c => c)
.Where(chunk => chunk.Count() > 1)
.Select(chunk => chunk.Key)
.ToArray();
// result = ['e']
Console.Write(String.Join(Environment.NewLine, result));
string name = "elements";
var myList = new List<char>();
var duplicates = new List<char>();
foreach (char res in name)
{
if (!myList.Contains(res))
{
myList.Add(res);
}
else if (!duplicates.Contains(res))
{
duplicates.Add(res);
}
}
foreach (char result in duplicates)
{
Console.WriteLine(result);
}
Console.ReadLine();
string is an array of chars. So, you can use your collection approach.
But, I would reccomend typed HashSet. Just load it with string and you'll get array of chars without duplicates, with preserved order.
take a look:
string s = "aaabbcdaaee";
HashSet<char> hash = new HashSet<char>(s);
HashSet<char> hashDup = new HashSet<char>();
foreach (var c in s)
if (hash.Contains(c))
hash.Remove(c);
else
hashDup.Add(c);
foreach (var x in hashDup)
Console.WriteLine(x);
Console.ReadKey();
Instead of a List<> i'd use a HashSet<> because it doesn't allow duplicates and Add returns false in that case. It's more efficient. I'd also use a Dictionary<TKey,Tvalue> instead of the list to track the count of each char:
string text = "elements";
var duplicates = new HashSet<char>();
var duplicateCounts = new Dictionary<char, int>();
foreach (char c in text)
{
int charCount = 0;
bool isDuplicate = duplicateCounts.TryGetValue(c, out charCount);
duplicateCounts[c] = ++charCount;
if (isDuplicate)
duplicates.Add(c);
}
Now you have all unique duplicate chars in the HashSet and the count of each unique char in the dictionary. In this example the set only contains e because it's three times in the string.
So you could output it in the following way:
foreach(char dup in duplicates)
Console.WriteLine("Duplicate char {0} appears {1} times in the text."
, dup
, duplicateCounts[dup]);
For what it's worth, here's a LINQ one-liner which also creates a Dictionary that only contains the duplicate chars and their count:
Dictionary<char, int> duplicateCounts = text
.GroupBy(c => c)
.Where(g => g.Count() > 1)
.ToDictionary(g => g.Key, g => g.Count());
I've shown it as second approach because you should first understand the standard way.
string name = "this is a a program program";
var arr = name.Split(' ').ToArray();
var dup = arr.Where(p => arr.Count(q => q == p) > 1).Select(p => p);
HashSet<string> hash = new HashSet<string>(dup);
string duplicate = string.Join(" ", hash);
You can do this through `LINQ
string name = "this is a a program program";
var d = name.Split(' ').GroupBy(x => x).Select(y => new { word = y.Key, Wordcount = y.Count() }).Where(z=>z.cou > 1).ToList();
Use LINQ to group values:
public static IEnumerable<T> GetDuplicates<T>(this IEnumerable<T> list)
{
return list.GroupBy(item => item).SelectMany(group => group.Skip(1));
}
public static bool HasDuplicates<T>(this IEnumerable<T> list)
{
return list.GetDuplicates().IsNotEmpty();
}
Then you use these extensions like this:
var list = new List<string> { "a", "b", "b", "c" };
var duplicatedValues = list.GetDuplicates();

Compare char in List C#

I wonder If there is any c# functions that checks if the letter exists more then once? In another word, I send a string to a function as parameter to check whether a letter exist more than once or not. For example the string "AABDCK" should return "A". Is there is any way to use dictionary??
Is there is any way to use dictionary??
Yes loop through each character in your string and track the number of occurrences of each character in a Dictionary<char, int>.
Dictionary<char, int> counts = new Dictionary<char, int>();
foreach (var ch in myString)
{
if (counts.ContainsKey(ch))
{
counts[ch]++;
}
else counts.Add(ch, 1);
}
Check the dictionary for keys where the value is > 1.
You can also do this with Linq. I'm not in front of a compiler, but it would look something like
List<char> multipleTimes = myString
.GroupBy(c => c)
.Select(g => new { Character = g.Key, Count = g.Count() })
.Where(a => a.Count > 1)
.Select(a => a.Character)
.ToList();
You could do it using linq, look the comments bellow to understand the code, for sample:
public string GetLetterWithMoreOccurrences(string text)
{
// check if the text was provided
if (string.IsNullOrEmpty(letter))
throw new ArgumentException("You must provide a text.", "text");
// if it is lower than 2 chars, return the first one
// I'm not sure if it is what you want, but let's consider it.
if (text.Length <= 2)
return text[0];
// find the first letter
var letter = text.GroupBy(c => c) // group by char
.Select(x => { Letter = x.Key, Total = x.Count() }) // in the group, count how many occurrences each letter has
.OrderByDescending(x => x.Total) // order by the total by descending
.First(); // get the first one
return letter;
}
and you can check:
var letter = GetLetterWithMoreOccurrences("AABDCK");
// should return "A"
Now, if you want all the letter that has more than one occurrences, you could try:
public string GetLetterAllDuplicates(string text)
{
// check if the text was provided
if (string.IsNullOrEmpty(letter))
throw new ArgumentException("You must provide a text.", "text");
// if it is lower than 2 chars, return the first one
// I'm not sure if it is what you want, but let's consider it.
if (text.Length <= 2)
return text[0];
// find the first letter
var letters = text.GroupBy(c => c) // group by char
// in the group, count how many occurrences each letter has
.Select(x => { Letter = x.Key, Total = x.Count() })
// get only the occurrences that has more than 1.. (you can change this parameter)
.Where(x => Total > 1)
// get it as array
.ToArray();
var result = string.Join(letters, "");
return result ;
}
And use it:
var text = GetLetterAllDuplicates("AABKCBD");
// should return "AB"
You can use:
String.IndexOf("A");
It will return the index of the First A Occurence.
If it returns -1, then there are not "A" occurrencies.
And here is my LINQ Implementation without using IndexOf:
string x = "AABCDEF";
List<char> repeatedCharacters = new List<char>();
var groupsOfChars = x.GroupBy(stringCharacter => stringCharacter);
groupsOfChars
.ToList()
.ForEach(item => {
if (item.Count() > 1) repeatedCharacters.Add(item.Key);
});
Or if you don't need the group:
string x = "AABCDEF";
List<char> repeatedCharacters = new List<char>();
x.GroupBy(stringCharacter => stringCharacter)
.ToList()
.ForEach(item => {
if (item.Count() > 1) repeatedCharacters.Add(item.Key);
});
And then you could check it:
repeatedCharacters.ForEach(item => {
Console.WriteLine(item.ToString());
});
//Since repeatedCharacters is an array, you can just simply do:
string stringOfRepeatedCharacters = repeatedCharacters.ToString();
//So you can easily convert the values to a String.
//[ 'A', 'B' ] is the result and it can be "AB".
it seems like bringing more wood into a forest, but it seems that some answers are incomplete or do not do exactly what was requested or are horrible complex:).
string input = "AABZFFZDCZZK";
//can handle null and empty string...
var rslt =
(string.IsNullOrEmpty(input) ? string.Empty : input)
.GroupBy(c => c)
.Select(gc => gc.Count() > 1 ? gc.Key : (char)0)
.Where(c => c != (char)0)
.OrderBy(c => c)//optional
.Aggregate(string.Empty, (c, n) => c + n)
;
The result is:
"AFZ"
The question was to provide back string with characters that occur multiple times.

How to count number of occurrence of each word in string?

I use the following code to extract words from string input, how can I get the occurrence of each words too?
var words = Regex.Split(input, #"\W+")
.AsEnumerable()
.GroupBy(w => w)
.Where(g => g.Count() > 10)
.Select(g => g.Key);
Instead of Regex.Split you can use string.Split and get the count for each word like:
string str = "Some string with Some string repeated";
var result = str.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
.GroupBy(r => r)
.Select(grp => new
{
Word = grp.Key,
Count = grp.Count()
});
If you want to filter out those words which are repeated 10 times atleast then you can add a condition before Select like Where(grp=> grp.Count >= 10)
For output:
foreach (var item in result)
{
Console.WriteLine("Word: {0}, Count:{1}", item.Word, item.Count);
}
Output:
Word: Some, Count:2
Word: string, Count:2
Word: with, Count:1
Word: repeated, Count:1
For case insensitive grouping you can replace the current GroupBy with:
.GroupBy(r => r, StringComparer.InvariantCultureIgnoreCase)
So your query would be:
var result = str.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
.GroupBy(r => r, StringComparer.InvariantCultureIgnoreCase)
.Where(grp => grp.Count() >= 10)
.Select(grp => new
{
Word = grp.Key,
Count = grp.Count()
});
Try this:
var words = Regex.Split(input, #"\W+")
.AsEnumerable()
.GroupBy(w => w)
.Select(g => new {key = g.Key, count = g.Count()});
Remove the Select statement to keep the IGrouping which you can use to view both the keys and take a count of values.
var words = Regex.Split(input, #"\W+")
.AsEnumerable()
.GroupBy(w => w)
.Where(g => g.Count() > 10);
foreach (var wordGrouping in words)
{
var word = wordGrouping.Key;
var count = wordGrouping.Count();
}
You could produce a dictionary like this:
var words = Regex.Split(input, #"\W+")
.GroupBy(w => w)
.Select(g => g.Count() > 10)
.ToDictionary(g => g.Key, g => g.Count());
Or if you'd like to avoid having to compute the count twice, like this:
var words = Regex.Split(input, #"\W+")
.GroupBy(w => w)
.Select(g => new { g.Key, Count = g.Count() })
.Where(g => g.Count > 10)
.ToDictionary(g => g.Key, g => g.Count);
And now you can get the count of words like this (assuming the word "foo" appears more than 10 times in input):
var fooCount = words["foo"];

Convert a delimited string to a dictionary<string,string>

I have a string in the format
=key1=value1=key2=value2=key3=value3
I need to convert it to a Dictionary<string,string> for the above mentioned key value pairs.
What would be the best way to go about this?
I've tried this:
var input = "key1=value1=key2=value2=key3=value3";
var dict = Regex.Matches(input , #"\s*(.*?)\s*=\s*(.*?)\s*(=|$)")
.OfType<Match>()
.ToDictionary(m => m.Groups[1].Value, m => m.Groups[2].Value);
This can be accomplished with a little Linq:
"=key1=value1=key2=value2=key3=value3"
.Split('=') // Split into an array of strings
.Skip(1) // Skip the first (empty) value
.Select((v, i) => new { v, i }) // Get value and index
.GroupBy(x => x.i / 2) // Group every pair together
.ToDictionary(g => g.First().v, // First item in group is the key
g => g.Last().v) // Last item in group is the value
var dict = new Dictionary<string,string>();
var input = str.Split(new [] { '=' },StringSplitOptions.RemoveEmptyEntries);
for(int i=0; i<input.Length; i+=2)
{
dict.Add(input[i], input[i+1]);
}

How to compare 2 list by characters content and its correspondents double values?

I have 2 lists: a string list and a double list with same length and with same index of correspondence. I need to compare all the strings, find the indexes of the list that has the same characters, independent of its order, and delete the highest double value that corresponds to both,
Example:
List<string> str= new List<string>();
str.add("efc");
str.add("abc");
str.add("cde");
str.add("cab");
str.add("fbc");
List<double> vlr= new List<double>();
vlr.add(0.1);
vlr.add(0.5);
vlr.add(0.4);
vlr.add(0.2);
vlr.add(0.3);
and this case, "abc" => (0.5) must be deleted because "cab" has the same characters AND lower correspondent value =>(0.2).
There is a lambda expression for this 2 arrays??
What I've tried:
var distinct = list .Select((str, idx) => new { Str = str, Idx = idx })
.GroupBy(pair => new HashSet<char>(pair.Str), HashSet<char>.CreateSetComparer())
.Select(grp => grp.OrderBy(p => p.Idx).First())
.ToList();
Here's one way to solve it:
// Pair the strings with their correspondence values
var pairs = str.Zip(vlr, (s, d) => new {s, d});
// Group using a sorted string, eliminating differences due to character order
var groups = pairs.GroupBy(x => new string(x.s.ToCharArray().OrderBy(c => c).ToArray()));
// For each group, retain the item with the lowest correspondence value
var filtered = groups.Select(x => x.OrderBy(y => y.d).First().s);
var newDict = str.Zip(vlr, (s, d) => new { s, d })
.GroupBy(x => String.Join("", x.s.OrderBy(y => y)))
.Select(g => g.OrderBy(x => x.d).First())
.ToDictionary(x => x.s, x => x.d);
here is the code:
var group = str.GroupBy(s => string.Join("", s.ToCharArray().OrderBy(c => c)));
var _vlr = group.Select(g => g.Min(s => vlr[str.IndexOf(s)]));
var _str = group.Select(g => g.OrderBy(s => vlr[str.IndexOf(s)]).First());
and the result:

Categories