簡體   English   中英

如何使我的程序更有效和緊湊地找到陣列中第N個最常見的元素?

[英]How can I make my procedure for finding the Nth most frequent element in an array more efficient and compact?

這是我提出的解決方案的一個例子

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

至少,我想弄清楚如何

  • 將查詢子句減少至少一個。 雖然我沒有看到任何冗余,但這是LINQ查詢的類型,我擔心所有創建的中間結構的開銷。

  • 弄清楚如何不在最后返回整個列表。 我只想要枚舉序列中的第二個元素; 我不需要返回整個列表,以便從中獲取單個元素。

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

我會這樣做的。

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
}

我開始回答,看到上面的答案,並認為我會比較它們。

這里是小提琴

我在每個上面放了一個秒表,並拿出每個蜱的數量。 結果是:

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

看來@ user3185569的算法比Hari略快,比OP的原始版本快30-40倍。 注意是@ user3185569上面的答案看起來他縮放時更快。

更新:我上面發布的數字是在我的電腦上運行的。 使用.net小提琴執行會產生不同的結果:

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

讓Berkser algortihm稍快一些。 我不完全清楚為什么會這樣,因為我的目標是相同的.net版本。

我想出了下面的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);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM