【问题标题】:Sorting a SortedDictionary of <String,int> Alphabetically, reverse Alphabetically, and the value's frequency对 <String,int> 的 SortedDictionary 按字母顺序、反向字母顺序和值的频率进行排序
【发布时间】:2012-10-25 20:16:06
【问题描述】:

我对 C# 和哈希表/字典的概念是全新的,并且一直在寻找一个直接的答案,但我找不到任何实际有效的解决方案(可能是由于我对主题),所以如果可能的话,我需要一个简单的解决方案。

另外,如果有区别的话,字典中的Strings 和ints 不是数据成员,甚至不是参数。

更多说明:

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

但是现在我只是想让字典的排序工作。

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

示例输出(按字母顺序): A开头的单词: 另一个冒险和 以字母 G 开头的字母: 伟大的 (等)

示例输出(按字母顺序反转): S开头的单词: 故事 G开头的单词: 伟大的 (等等)

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

【问题讨论】:

  • 不清楚你想做什么或什么不起作用。你能展示你的尝试吗?
  • 添加了更多描述。至于代码,我确定我基本上需要从头开始。
  • 输入示例、所需输出等会有所帮助
  • SortedDictionary 实际上并未实现为哈希表,而是实现为基于树的数据结构。

标签: c# dictionary alphabetical sorteddictionary


【解决方案1】:

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

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

【讨论】:

  • 感谢您提供有用的帖子,但我需要您在单独的 TUI 类中发布的代码。在插入并修复项目规范时,for循环会产生此错误“foreach语句无法对void类型的变量进行操作,因为void不包含'GETenumerator'的公共定义”你能解释这个错误的含义并给我一些建议吗怎么解决?
  • 不用担心 - 我已将代码放在与 UI 相同的层用于演示目的。要使其作为库工作,请创建返回 IEnumerable> 结果的函数,然后返回 OrderBys 的结果(或将 console.writeline 替换为 yield return 语句以获得更简单的解决方案)。
  • 对不起,您能用更简单的方式解释一下,或者给我举个例子吗?
  • 不用担心,我已将代码重构为一个单独的类 - 只需使用 WordCount 类 - 它之前的内容(在程序中)向您展示了如何使用该类。
  • 再次感谢您的帮助。我还没有能够测试最后一个帖子,但如果遇到更多问题,我会回到这里。
【解决方案2】:

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

【讨论】:

  • 我也不确定该怎么做。
  • LINQ 的 OrderBy 方法是获取任何数据结构并返回按特定庄园排序的所有值的有效方法。
  • 我试过了。然而,关于如何使用 OrderBy 方法的每个示例只会导致更多的争议,因为我似乎永远无法理解参数是什么以及它们在做什么。此外,我见过的大多数示例都引用了我没有的已保存变量或数据成员。
猜你喜欢
  • 2020-10-12
  • 2019-02-03
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多