按字母顺序排序<string,int>的SortedDictionary,按字母顺序排序,以及值的频率</string,int>

时间:2012-10-25 20:16:06

标签: c# dictionary alphabetical sorteddictionary

我对C#和哈希表/词典的概念都很陌生,并且一直在寻找这个问题的直接答案,但我找不到任何实际可行的解决方案(可能是因为我对此无知如果可能的话,我需要一个简单的解决方案。

此外,如果它有所不同,字典中的Stringint不是数据成员甚至是参数。

更多说明:

整个程序,是通过文本文件或直接用户输入导入单词然后保存它们和它们出现的次数(AKA存储在Dictionary/Sorteddictionary中)然后允许用户按字母顺序重新组织数据,按字母顺序反向,或通过频率和/或将它们打印到控制台或将数据写入新的.txt文件。

但是现在我只是试图让字典的排序起作用。

示例输入: 另一个伟大的故事和另一个伟大的冒险。

示例输出(按字母顺序排列): 以字母A开头的单词: 另一次冒险和 以字母G开头的信: 大 (ECT)。

示例输出(按字母顺序反向): 以字母S开头的单词: 故事 以字母G开头的单词: 大 (ECT)。

输出(频率): 出现2次的单词数量: 另一个伟大 发生一次的单词数量: 和冒险故事。

2 个答案:

答案 0 :(得分:0)

由于您不是始终在单个一致排序的庄园中显示数据,因此我没有看到任何令人信服的理由将数据存储在已排序的庄园中。您可能最好只是存储您想要的数据,然后在用户请求在某个特别排序的庄园中查看数据时对其进行排序。

答案 1 :(得分:0)

希望这会有所帮助。我不确定这是解决问题的最佳方法,但它应该可以帮助您熟悉一些选项/看看为什么这里的一些人建议反对它。如果您让我们更多地了解您要做的事情,我们可以更好地建议其他方法。

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)));
                }
            }
        }

    }
}
祝你好运/希望你到目前为止享受c#。

修改

根据您问题中的新信息,我尝试了一个更简洁的解决方案:

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()));
            }
        }
    }
}

修改

这是与类中的功能相同的代码,并且输出保存在程序中:     使用系统;     使用System.Collections.Generic;     使用System.Linq;     使用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()));
        }
    }
}