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??
-
what should be the result for `AABB` – M.kazem Akhgary Oct 30 '15 at 21:50
-
@M.kazemAkhgary ex: Assert.Equals('A', pg.GetCommonChar("AABCNMHM")); so in this example it should return A and so on. – moji Oct 30 '15 at 22:08
-
Can be solved pretty easily with LINQ, pls look on my answer. – ipavlu Oct 31 '15 at 00:00
-
Although Linq may be the most common way to solve this problem today, the OP asked about solving it with a dicitonary, not with Linq. The question is therefore not a duplicate of "C# LINQ find duplicates in List". – Eric J. Nov 02 '15 at 19:05
4 Answers
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();

- 147,927
- 63
- 340
- 553
-
the guy who downvoted probably did not understand question or he didnt like you ;) – M.kazem Akhgary Oct 30 '15 at 22:03
-
-
Perhaps the reason for down vote is, that the result does not comply with requested output format? Just guess, I do not down vote by the design, unless it is really terrible answer, and this answer does not seem to be bad... – ipavlu Oct 31 '15 at 00:07
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"

- 37,948
- 19
- 131
- 194
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".

- 1,054
- 9
- 15
-
-
IndexOf would do it, then you can search not from zero but the last position of the last "A" occurence. – kevinrodriguez-io Oct 30 '15 at 21:36
-
That would work but it's not very efficient to scan the string multiple times. – Eric J. Oct 30 '15 at 21:39
-
It won't scan the entire string multiple times since you could set from which character(index) start to read, i think. – kevinrodriguez-io Oct 30 '15 at 21:40
-
1Your assumption is that he's looking for multiple occurrences of "A". My understanding (could be wrong) is that he's looking for any characters that occur multiple times. If my understanding is correct, you have to scan the string multiple times, once for each distinct character. If your understanding of the problem is correct, you are right there would be only one scan. – Eric J. Oct 30 '15 at 21:46
-
The Linq implementation you just added scans the string once to group it, then once for each letter. – Eric J. Oct 30 '15 at 21:47
-
You are completely right now that i see what you were meaning that the IndexOf has to scan the entire string more than 1 time. The only thing i could think is to save a char[] to store tthe string and use that char[] as reference, but you get whole the string duplicated on system memory – kevinrodriguez-io Oct 30 '15 at 21:50
-
1@darkndream Nice effort, everyone trying to answer is a good thing, sort of going out with naked skin :). Here I would just note, that the result does not comply with the request, but the main issue is that LINQ is best if it can chain operations. Best result can be get if data are transformed as far as possible to something, that can then force enumeration. Like Aggregate for example. So here the best option is to transform grouped characters into character and aggregate to string. – ipavlu Oct 31 '15 at 00:17
-
@ipavlu yeah, it could be all chained, the result is a char[] which can be easily converted to a String, in this kind of questions the best method is defined by speed of execution. What i don't see is: Even if i chain all the linq statements, which one would be the fastest? – kevinrodriguez-io Oct 31 '15 at 00:27
-
Usually, the chaining one is the fastest, as the chain is going through items once, instead twice or multiple times. And methods like Where helps to improve speed, as it is skipping some results. But in your case, you GroupBy some list, that is creating some container for new kind data and enumerator over that, then in next step you force it to enumerate itself into list in order to use List
.ForEaach. In my answer, chaining, it would be skipped and should be faster... – ipavlu Oct 31 '15 at 23:42 -
... There are exceptions, a super large dataset, chaining is sometimes less effective, than going through one transformation after another, but in that kind scenario it is about benchmarking anyway, here it is not not the case. I just want to mention that as a special exception... – ipavlu Oct 31 '15 at 23:45
-
Thanks for the remarks. I think the tolist conversion is unnecesary since i did it to make a foreach loop – kevinrodriguez-io Oct 31 '15 at 23:49
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.

- 1,617
- 14
- 24