2016-06-24 3 views
2

は、私は非常に少なくとも配列内のN番目に頻繁に出現する要素をより効率的かつコンパクトに見つけるための手続きをどのようにすることができますか?ここで

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

public class Program 
{ 
    public static void Main() 
    { 
     int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 }; 
     var countlist = arr.Aggregate(new Dictionary<int,int>(), (D,i) => { 
             D[i] = D.ContainsKey(i) ? (D[i] + 1) : 1; 
             return D; 
             }) 
          .AsQueryable() 
          .OrderByDescending(x => x.Value) 
          .Select(x => x.Key) 
          .ToList(); 
     // print the element which appears with the second 
     // highest frequency in arr 
     Console.WriteLine(countlist[2]); // should print 3 
    } 
} 

を思い付いたソリューションの一例ですが、私は少なくとも1でクエリ句を削減する方法に

  • 把握したいと思います。私は冗長性は見ませんが、これはLINQクエリの一種です。ここでは、作成されたすべての中間構造のすべてのオーバーヘッドについて心配しています。

  • 最後にリスト全体を返さない方法を解説します。列挙されたシーケンスの2番目の要素がほしいだけです。 1つの要素を取り除く目的でリスト全体を返す必要はありません。

+0

にessentialyである、それは大丈夫です、あなたが探しているとして、辞書を思い付いたあなたは.SKIP()と.FirstOrDefaultを(使用する場合)直前に.ToList()? – shole

答えて

3
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 }; 

var lookup = arr.ToLookup(t => t); 
var result = lookup.OrderByDescending(t => t.Count()); 

Console.WriteLine(result.ElementAt(1).Key); 
2

私はこれを行うだろう。

int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 }; 


int rank =2; 
var item = arr.GroupBy(x=>x)   // Group them 
    .OrderByDescending(x=>x.Count()) // Sort based on number of occurrences 
    .Skip(rank-1)      // Traverse to the position 
    .FirstOrDefault();     // Take the element 


if(item!= null) 
{ 
    Console.WriteLine(item.Key); 
    // output - 3 
} 
1

私は答え始めて、上記の答えを見て、代わりにそれらを比較すると思った。

ここにはFiddle hereがあります。

私はそれぞれにストップウォッチを付けて、それぞれに目盛りを付けました。結果は以下の通りであった

Orignal: 50600 
Berkser: 15970 
Tommy: 3413 
Hari: 1601 
user3185569: 1571 

user3185569がハリよりも若干速いアルゴリズムを持っており、OPのoriganalバージョンよりも約30〜40倍高速です@それが表示されます。 @ user3185569の答えは、スケーリングされたときに彼の方が速いと思われます。

更新:上記の番号は私のPC上で実行されました。わずかに速いBerkser algortihmを置く

Orignal: 46842 
Berkser: 44620 
Tommy: 11922 
Hari: 13095 
user3185569: 16491 

:実行するための.NETフィドルを使用すると、異なる結果が得られます。私は同じネット版をターゲットにしているので、なぜこれが当てはまるのか完全にはっきりしていません。

+0

私は同じリンクを使ってほとんど同じ数字を得ることができません、私はハリスのために '12663'を得ています – user3185569

+0

それは面白いです。私が投稿した数字は私のPCからのものでした。そして、コードはフィドルに投稿されました。私は複数の時間を再実行し、毎回ほぼ同じ数字を取得しています。なぜフィドルでそれがどう違うのか分かりません。 –

+0

私の答えを確認できますか?私はそれがこれらすべてよりはるかに速いと思う。 – user3185569

1

私はLINQの次のマッシュと注文した辞書

 void Run() 
    { 
     int[] arr = new int[] { 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4 }; 
     int[] unique = arr.Distinct().ToArray(); 
     Dictionary<int, int> dictionary = unique.ToDictionary(k => k, v => 0); 

     for(int i = 0; i < arr.Length; i++) 
     { 
      if(dictionary.ContainsKey(arr[i])) 
      { 
       dictionary[arr[i]]++; 
      } 
     } 

     List<KeyValuePair<int, int>> solution = dictionary.ToList(); 
     solution.Sort((x,y)=>-1* x.Value.CompareTo(y.Value)); 
     System.Console.WriteLine(solution[2].Key); 
    } 
関連する問題