计算数组中不同元素数量的最快方法

Posted

技术标签:

【中文标题】计算数组中不同元素数量的最快方法【英文标题】:Fastest way to count number of distinct elements in array 【发布时间】:2020-01-17 11:27:59 【问题描述】:

我有这样一类对象:

public class Individual

    public double[] Number  get; set;  = new double[2] 0.0, 0.0 ;

我将这些类存储在字典列表中,并为 Individual.Number 提供值:

selection = List<Dictionary<int, Individual>>

现在,我必须计算Individual.Number(在整个列表中)的不同值的数量。到目前为止我所做的是:

selection.Values.SelectMany(list => list.Number).Distinct().Count();

我想知道这是否是最快的计数方法?如何提高性能?

谢谢,

【问题讨论】:

你的方法很好。我建议避免使用microoptimizing,除非您遇到实际性能问题。 【参考方案1】:

Distinct() 方法在内部创建一个新的Set&lt;T&gt; 而不指定大小。

如果您对元素的数量有一个模糊的概念,这可以防止多次分配(和内存移动)。

因为你只想要 Count() 你可以直接包含它(Credits @TimSchmelter)。

    public static int OptimizedDistinctAndCount<TSource>(this IEnumerable<TSource> source, int numberOfElements) 
        if (source == null) throw Error.ArgumentNull("source");
        var set = new HashSet<TSource>(numberOfElements);
        foreach (TSource element in source) 
           set.Add(element);
        
        return set.Count;
    

然后你可以使用:

selection.Values.SelectMany(list => list.Number).OptimizedDistinctAndCount(123);

【讨论】:

【参考方案2】:

您对此有何看法?

public class Individual

  public double[] Numbers  get; set; 
  public Individual()
  
    Numbers = new double[0];
  
  public Individual(double[] values)
  
    Numbers = values/*.ToArray() if a copy must be done*/;
  


class Program

  static void Main()
  
    // Populate data
    var selection = new List<Dictionary<int, Individual>>();
    var dico1 = new Dictionary<int, Individual>();
    var dico2 = new Dictionary<int, Individual>();
    selection.Add(dico1);
    selection.Add(dico2);
    dico1.Add(1, new Individual(new double[]  1.2, 1.3, 4.0, 10, 40 ));
    dico1.Add(2, new Individual(new double[]  1.2, 1.5, 4.0, 20, 40 ));
    dico2.Add(3, new Individual(new double[]  1.7, 1.6, 5.0, 30, 60 ));
    // Count distinct
    var found = new List<double>();
    foreach ( var dico in selection )
      foreach ( var item in dico )
        foreach ( var value in item.Value.Numbers )
          if ( !found.Contains(value) )
            found.Add(value);
    // Must show 12
    Console.WriteLine("Distinct values of the data pool = " + found.Count);
    Console.ReadKey();
  

这种方法消除了一些调用方法的时间。

进一步的优化将使用 for 循环而不是 foreach,并且可能使用链表而不是 List(更快但需要更多内存)。

【讨论】:

以上是关于计算数组中不同元素数量的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Diesel 计算数组列中不同元素的数量?

最快的方法来计算没有碰撞的整数数组的哈希值

查找数组的所有元素是不是不同的最快方法?

查找范围内元素数量的最快方法

在numpy中计算超过阈值的数组值的最快方法

计算linq中两个数组中相同元素的数量