2017-02-24 12 views
0

私はC#を使って周波数解析コンソールプログラムを作る必要があります。それは、テキストファイルから10の最も頻繁な文字を表示する必要があります。私はプログラムによって読み込まれた最初の10文字と各文字の頻度を表示することができました。しかし、私は辞書のソート方法を知らない。これはこれまでのコードです。C#.netで辞書をソートする方法

大文字と小文字の区別がついたモード(現時点で)と大文字と小文字を区別しないで、頻度分析のオプションもユーザーに与えなければなりません。この問題の助けにも感謝します。ありがとうございました!

static void Main(string[] args) 
    { 
     // 1. 
    // Array to store frequencies. 
    int[] c = new int[(int)char.MaxValue]; 

     // 2. 
     // Read entire text file. 
     // string root = Server.MapPath("~"); 
     // string FileName = root + "/App_Data/text.txt"; 

     //string s = File.ReadAllText(FileName); 

     foreach (string line in  File.ReadLines(@"c:\Users\user\Documents\Visual Studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\App_Data\text.txt", Encoding.UTF8)) { 

      var fileStream = new FileStream(@"c:\Users\user\Documents\Visual Studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\App_Data\text.txt", FileMode.Open, FileAccess.Read); 
     using (var streamReader = new StreamReader(fileStream, Encoding.UTF8)) 
     { 
       string line2; 
       while ((line2 = streamReader.ReadLine()) != null) 
      { 
       // process the line 


       // 3. 
       // Iterate over each character. 
       foreach (char t in line) 
       { 
        // Increment table. 
        c[(int)t]++; 
       } 

        // 4. 
        // Write all letters found. 
        int counter = 0; 
        for (int i = 0; i < (int)char.MaxValue; i++) 
       { 


         if (c[i] > 0 && counter < 11 && 
         char.IsLetterOrDigit((char)i)) 
        { 
          ++counter; 
          Console.WriteLine("Letter: {0} Frequency: {1}", 
          (char)i, 
          c[i]); 
        } 
       } 
      } 
     } 
      Console.ReadLine(); 

    } 

    } 
+0

https://www.dotnetperls.com/sort-dictionaryこのリンクをクリックしてください。 – Sameer

+0

'Dictionary'はソートできません。順序の概念はありません。あなたができることは辞書をList/Enumerableに変換し、@ aquinasのようにソートします。 –

答えて

0

配列ではなく、ここではC#で、実際の辞書の種類を使用して容易になるだろう:

Dictionary<char, int> characterCountDictionary = new Dictionary<char, int>(); 

がまだ存在し(との値を挿入しない場合は、キーを追加1)、または存在する場合は値をインクリメントします。次に、辞書のキーをリストとして取り出してソートし、値を見つけるために繰り返します。大文字と小文字を区別しない場合は、大文字を小文字に変換してから辞書に挿入します。

ここでは、MSDNのページには、辞書のための例のためです:https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx#Examples

3

あなたがしたいすべての周波数を発見したのであれば、あなたはどの辞書をしたいが、LINQのません。このようなタスクは、LINQのは、のために設計されているものです。

... 
using System.Linq; 
... 

static void Main(string[] args) { 
    var result = File 
    .ReadLines(@"...", Encoding.UTF8) 
    .SelectMany(line => line)    // string into characters 
    .Where(c => char.IsLetterOrDigit(c)) 
    .GroupBy(c => c) 
    .Select(chunk => new { 
     Letter = chunk.Key, 
     Count = chunk.Count() }) 
    .OrderByDescending(item => item.Count) 
    .ThenBy(item => item.Letter)   // in case of tie sort by letter 
    .Take(10) 
    .Select(item => $"{item.Letter} freq. {item.Count}"); // $"..." - C# 6.0 syntax 

    Console.Write(string.Join(Environment.NewLine, result)); 
} 
0

、それは非常に簡潔なので、私は@Dmitry Bychenkoの答えが好きです。しかし、非常に大きなファイルをお持ちの場合は、そのソリューションが最適ではない場合があります。その理由は、その解決策は、ファイル全体をメモリに読み込んで処理する必要があるからです。そこで、私のテストでは、500MBのファイルに対して約1GBのメモリ使用量を得ました。下記の解決策は、簡潔ではありませんが、一定のメモリ(基本的に0)を使用し、私のテストではLinqバージョンより高速または高速で動作します。

Dictionary<char, int> freq = new Dictionary<char, int>(); 

using (StreamReader sr = new StreamReader(@"yourBigFile")) { 
    string line; 
    while ((line = sr.ReadLine()) != null) { 
     foreach (char c in line) { 
      if (!freq.ContainsKey(c)) { 
       freq[c] = 0; 
      } 
      freq[c]++; 
     } 
    } 
} 

var result = freq.Where(c => char.IsLetterOrDigit(c.Key)).OrderByDescending(x => x.Value).Take(10); 
Console.WriteLine(string.Join(Environment.NewLine, result)); 
関連する問題