在阵列中获取最频繁和最相似值的最快方法?

时间:2013-08-20 17:06:26

标签: c# sorting integer similarity

我在C#中有一个int数组,我希望获得整个数组的5%,就像新数组包含最常见的相似值一样。 举个例子,假设我有一个包含100个条目的数组,其中包含40个兄弟姐妹20(15到25)。我想要的是将20作为最常见的值(包括它的兄弟)检测为新数组,然后检测新数组中最常见的5个值。 我需要在ASP.net网站上运行代码,因此,我需要一个快速的算法。 有人可以帮我这个吗?

2 个答案:

答案 0 :(得分:3)

您可以通过对值进行分组,按计数排序,然后获取它们直到填充所需的5%数组来构建一个简单的算法,如下所示:

// Build a set of {Value, Count} pairs using LINQ
var counts = data
    .GroupBy(v => v)
    .Select(g => new {
        Value = g => Key
    ,   Count = g.Count()
    }).OrderByDescending(p => p.Count)
    .Take(5);

编辑:

  

阵列大小可能大到1024 * 1024,范围介于0到255之间

由于范围非常小,您可以使用计数数组而不是组,如下所示:

int counts = new int[256];
foreach (var b in data) {
    counts[b]++;
}

现在您可以运行Quick Select Algorithm来选择第五项。以下an answer提供了QuickSelect的C#实现。

var fifth = QuickSelect(counts, 5);
var res = new List<KeyValuePair<int,int>>();
for (int i = 0 ; i != counts.Length && res.Length != 5 ; i++) {
    if (counts[i] >= fifth) {
        res.Add(new KeyValuePair<int,int>(i, counts[i]));
    }
}

您可能希望将快速选择算法替换为具有相同线性性能但未随机化的median-of-medians algorithm

答案 1 :(得分:2)

var numbersByOccurrence = from numbers in yourNumberArrayVariable
                          group numbers by numbers into g
                          select new { Number = g.Key, Count = g.Count() };

var limitedSize = numbersByOccurrence.OrderByDescending(n => n.Count).Take(5);

现在你有一个5个对象的变量(你可以作为一个数组或列表进行转换),你可以轻松访问一个Number和Count变量。