[Solved] Sorting a SortedDictionary of Alphabetically, reverse Alphabetically, and the value’s frequency


Hope this helps. I’m not sure it’s the best way to approach your problem, but it should help you to familiarise yourself with some of the options / see why some of the guys on here are advising against it. If you let us know more about what you’re trying to do we can better advise alternate approaches.

using System;
using System.Collections.Generic;
using System.Linq;

namespace StackOverflow.Demos
{
    class Program
    {

        const string OutputFormat = "{0}: {1}";
        public static void Main(string[] args)
        {
            new Program();
            Console.WriteLine("Done");
            Console.ReadKey();
        }
        public Program()
        {
            SortedDictionary<string, int> dic = new SortedDictionary<string, int>();
            dic.Add("a", 1);
            dic.Add("b", 2);
            dic.Add("d", 2);
            dic.Add("c", 1);
            dic.Add("e", 1);
            dic.Add("f", 3);
            dic.Add("g", 4);
            dic.Add("h", 2);
            dic.Add("i", 2);

            OutputByKeyAsc(dic);
            OutputByKeyDesc(dic);
            OutputByValueFrequency(dic);
        }

        void OutputByKeyAsc(SortedDictionary<string, int> dic)
        {
            Console.WriteLine("OutputByKeyAsc");
            foreach (string key in dic.Keys)
            {
                Console.WriteLine(string.Format(OutputFormat, key, dic[key]));
            }
        }

        void OutputByKeyDesc(SortedDictionary<string, int> dic)
        {
            Console.WriteLine("OutputByKeyDesc");
            foreach (string key in dic.Keys.Reverse())
            {
                Console.WriteLine(string.Format(OutputFormat, key, dic[key]));
            }
        }

        void OutputByValueFrequency(SortedDictionary<string, int> dic)
        {
            Console.WriteLine("OutputByValueFrequency");

            IEnumerable<KeyValuePair<int,int>> values = 
                (
                    from sortedItem 
                    in 
                    (
                        from entry 
                        in dic 
                        group entry 
                        by entry.Value
                        into result
                        select new KeyValuePair<int,int>(result.Key , result.Count())
                    )
                    orderby sortedItem.Value descending
                    select sortedItem
                ).ToArray();

            foreach (KeyValuePair<int, int> value in values)
            {
                foreach (KeyValuePair<string, int> item in dic.Where<KeyValuePair<string, int>>(item => item.Value == value.Key))
                {
                    Console.WriteLine(string.Format(OutputFormat, item.Key, string.Format(OutputFormat, item.Value, value.Value)));
                }
            }
        }

    }
}

Good luck / hope you’re enjoying c# so far.

EDIT

Based on the new info in your question here’s my attempt at a neater solution:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace StackOverflow.Demos
{
    class Program
    {

        const string OutputFormat = "{0}: {1}";
        public static void Main(string[] args)
        {
            new Program("Another great story and another great adventure.");
            Console.WriteLine("Done");
            Console.ReadKey();
        }
        public Program(string userInput)
        {
            //break string into words
            IEnumerable<IGrouping<string, int>> words = Regex.Split(userInput, @"\W+").GroupBy(word => word.ToLowerInvariant(), word => 1); //nb converting word to lower case to avoid case sensitive comparisons in grouping - I can keep the original value(s) by replacing "word => 1" with "word => word" if needed

            Console.WriteLine("\nWords in alphabetic order");
            foreach (IGrouping<string, int> wordInfo in words.OrderBy(word => word.Key))
            {
                Console.WriteLine(string.Format(OutputFormat, wordInfo.Key,wordInfo.Count()));
            }

            Console.WriteLine("\nWords in descending alphabetic order");
            foreach (IGrouping<string, int> wordInfo in words.OrderByDescending(word => word.Key))
            {
                Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Count()));
            }

            Console.WriteLine("\nWords by frequency (desc)");
            foreach (IGrouping<string, int> wordInfo in words.OrderByDescending(word => word.Count()))
            {
                Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Count()));
            }
        }
    }
}

EDIT

Here’s the same code with the functionality in a class and the output kept in the program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace StackOverflow.Demos
{
    class Program
    {

        const string OutputFormat = "{0}: {1}";
        public static void Main(string[] args)
        {
            new Program("Another great story and another great adventure.");
            Console.WriteLine("Done");
            Console.ReadKey();
        }
        public Program(string userInput)
        {
            WordCounter myWordCounter = new WordCounter(userInput);
            Console.WriteLine("\n**Alphabetical**");
            foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByWordAlphabeticalDesc())
            {
                Console.WriteLine(string.Format(OutputFormat,wordInfo.Key, wordInfo.Value));
            }
            Console.WriteLine("\n**Alphabetical Desc**");
            foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByWordAlphabeticalDesc())
            {
                Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Value));
            }
            Console.WriteLine("\n**Frequency Desc**");
            foreach (KeyValuePair<string, int> wordInfo in myWordCounter.GetWordCountByFrequency())
            {
                Console.WriteLine(string.Format(OutputFormat, wordInfo.Key, wordInfo.Value));
            }
        }

    }

    public class WordCounter
    {
        string sentance;
        IEnumerable<IGrouping<string, int>> words;
        public WordCounter(string sentance)
        {
            this.sentance = sentance;
            GetWords();
        }
        void GetWords()
        {
            this.words = Regex.Split(this.sentance, @"\W+").GroupBy(word => word.ToLowerInvariant(), word => 1);
        }
        public IEnumerable<KeyValuePair<string, int>> GetWordCountByWordAlphabetical()
        {
            return this.words.OrderBy(word => word.Key).Select(wordInfo => new KeyValuePair<string,int>(wordInfo.Key, wordInfo.Count()));
        }
        public IEnumerable<KeyValuePair<string, int>> GetWordCountByWordAlphabeticalDesc()
        {
            return this.words.OrderByDescending(word => word.Key).Select(wordInfo => new KeyValuePair<string, int>(wordInfo.Key, wordInfo.Count()));
        }
        public IEnumerable<KeyValuePair<string, int>> GetWordCountByFrequency()
        {
            return this.words.OrderByDescending(word => word.Count()).Select(wordInfo => new KeyValuePair<string, int>(wordInfo.Key, wordInfo.Count()));
        }
    }
}

5

solved Sorting a SortedDictionary of Alphabetically, reverse Alphabetically, and the value’s frequency