I'm working on a program where the user has to input some sort of string in, and the program will store it in a List or an Array, then count how many times the item was repeated.
The three items that are repeated the most are then displayed in descending order of number of repetitions (1st has 10 repeats, 2nd has 9, 3rd has 8)
It sounded simple. Since I have no idea how many people will input a string in, I used a list, then followed this example:
foreach (string value in list.Distinct())
{
System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", value, list.Count(v => v == value));
}
But for some reason, .Distinct() does not appear after my list name. Did I do something wrong? Does this have something to do with my C#, which is NOT a C# 3.0? The example never mentioned anything about adding another reference, or the like.
Is there any other way I can do this?
.Distinct()
is a LINQ extension method. You need .NET 3.5+ to use it.
With that said, you don't need LINQ to do what you want. You could easily use other collection classes and a bit of arithmetic to get your results.
// Create a dictionary to hold key-value pairs of words and counts
IDictionary<string, int> counts = new Dictionary<string, int>();
// Iterate over each word in your list
foreach (string value in list)
{
// Add the word as a key if it's not already in the dictionary, and
// initialize the count for that word to 1, otherwise just increment
// the count for an existing word
if (!counts.ContainsKey(value))
counts.Add(value, 1);
else
counts[value]++;
}
// Loop through the dictionary results to print the results
foreach (string value in counts.Keys)
{
System.Diagnostics.Debug
.WriteLine("\"{0}\" occurs {1} time(s).", value, counts[value]);
}
If you don't have C#3.0, then you don't have extension methods.
If you don't have .NET3.5 then you don't have any of the Linq extension methods to call as statics.
You can add your own for quite a few of these pieces of functionality:
public static IEnumerable<T> Distinct(IEnumerable<T> src, IEqualityComparer<T> eCmp)
{
Dictionary<T, bool> fakeHashSet = new Dictionary<T, bool>(eCmp);
//When I coded for 2.0 I had my own custom HashSet<T>, but that's overkill here
bool dummy;
foreach(T item in src)
{
if(!fakeHashSet.TryGetValue(item, out dummy))
{
fakeHashSet.Add(item, true);
yield return item;
}
}
}
public static IEnumerable<T> Distinct(IEnumerable<T> src)
{
return Distinct(src, EqualityComparer<T>.Default);
}
public delegate TResult Func<T, TResult>(T arg);//we don't even have this :(
public static int Count(IEnumerable<T> src, Func<T, bool> predicate)
{
int c = 0;
foreach(T item in src)
if(predicate(item))
++c;
return c;
}
Because we don't have extension syntax, or lamdbas, we have to call them like:
foreach (string value in Distinct(list))
{
System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", value, Count(list, delegate(string v){return v == value;}));
}
In all, we can implement much of Linq-to-objects with C#2.0, and many of us did, but it's nowhere near as friendly, and of course we can't map to other query providers.
In this case though, you'd be faster just doing the count directly:
Dictonary<string, int> counts = new Dictionary<string, int>();
foreach(string value in list)
{
if(counts.ContainsKey(value))
counts[value]++;
else
counts[value] = 1;
}
foreach(KeyValuePair<string, int> kvp in counts)
System.Diagnostics.Debug.WriteLine("\"{0}\" occurs {1} time(s).", kvp.Key, kvp.Value));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With