1

I have to generate randomly letters in a string

this.text = "";
Random rndChar = new Random();

for (int i = 0; i < 50; i++)
{
    this.text = this.text + (char)rndChar.Next(65,91);
}

The result is something about GUHZBVUTSUZHBF...

Now i have to generate a list of the characters in ascending order with the number of times each character has been repeated. I tried it with

SortedList letters = new SortedList();
for(int i = 0; i < 50; i++)
{
    letters.Add(this.text[i], i);
}

foreach (Char entry in letters.Values)
    Console.WriteLine(entry);

, but that doesn't work:

"System.ArgumentException: 'Item has already been added. Key in dictionary: 'J' Key being added: 'J'' ."

What does that mean? How can i solve that issue?

maccettura
  • 10,514
  • 3
  • 28
  • 35
El Gato
  • 21
  • 2
  • 1
    You cannot add duplicate keys in a [`SortedList`](https://msdn.microsoft.com/en-us/library/system.collections.sortedlist.add(v=vs.110).aspx), thats why you are getting that error. So stop doing that – maccettura May 02 '18 at 18:25
  • 1
    `SortedList` is a terrible name because it [isn't a list](https://stackoverflow.com/questions/3663613/). – Dour High Arch May 02 '18 at 18:28
  • 2
    @Harsh this is not a duplicate. you would have to know that sorted list is a dictionary first – johnny 5 May 02 '18 at 18:37
  • 1
    I agree, this is not a duplicate (at least of the linked question) – maccettura May 02 '18 at 18:38
  • 1
    Also, `letters.Values` is an `int`. `letters.Keys` is a `char`. So you're going to end up with a sorted list based on the character, not the count. And you can't have the count as a key since there may be duplicates. – Rufus L May 02 '18 at 18:39
  • @johnny5 Yes, you'll have to know that it is a dictionary. And the OP could have known that by reading the Error message? – Harsh May 02 '18 at 18:44
  • I think it's a dupe based on the exact same error message, and that the resolution to that error message is the same. – Rufus L May 02 '18 at 18:46
  • 1
    @Harsh, If I were new to programming and I were to see that message I would be even more confused because I don't have a dictionary on the page. – johnny 5 May 02 '18 at 18:46
  • @johnny5 And then you would set the cursor on `SortedDictionary` and press `F12`, and see: `public class SortedList : IDictionary, ICollection, IEnumerable, ICloneable` – Rufus L May 02 '18 at 18:47
  • Here is my [solution](https://dotnetfiddle.net/lrP3aQ) – Grizzly May 02 '18 at 18:48
  • @johnny5 Especially as a new programmer, we should be learning to infer from analyzing the error message. – Harsh May 02 '18 at 18:48
  • 1
    @RufusL, New people might not know to check the definition either – johnny 5 May 02 '18 at 18:49
  • @johnny5 Then that is the first thing to learn :) – Harsh May 02 '18 at 18:50

1 Answers1

1

As noted in the comments, the reason SortedList causes a problem here is that it's actually a dictionary, despite the name. You can't call Add with the same key twice. (You can use the indexer to set a new value for a key, whether it previously existed or not, but Add checks whether there's already a value for the key.)

You could use SortedList for its sortedness, but keep the count in the value. That's harder than it needs to be though. I would use LINQ for this - it makes it very easy to do both aspects of this.

var orderedGroups = text
   .GroupBy(c => c, (c, g) => new { Letter = c, Count = g.Count() })
   .OrderBy(g => g.Key);

foreach (var element in orderedGroups)
{
    Console.WriteLine(element);
}

It also makes it easier to do the first part, actually - no need for a for loop and string concatenation. Here's a complete example:

using System;
using System.Linq;

public class Program
{
    static void Main()
    {
        Random rng = new Random();
        var letters = Enumerable.Range(0, 50)
            .Select(_ => (char) rng.Next(65,91))
            .ToArray();

        Console.WriteLine($"Letters: {new string(letters)}");
        var orderedGroups = letters
            .GroupBy(c => c, (c, g) => new { Letter = c, Count = g.Count() })
            .OrderBy(g => g.Key);

        foreach (var element in orderedGroups)
        {
            Console.WriteLine(element);
        }
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194