C# 遍历列表的最快方式<;字节[]>;由1000个元素组成

C# 遍历列表的最快方式<;字节[]>;由1000个元素组成,c#,list,optimization,foreach,fingerprint,C#,List,Optimization,Foreach,Fingerprint,我的数据库中有一千个指纹存储在一个Byte[]数组中,我正在尝试对指纹进行1:N验证,这意味着我需要比较传感器给出的指纹和数组中的指纹 但是这个过程花费的时间太长了,我正在使用forEach循环迭代数组中的所有指纹,并调用验证方法来比较两个数组以找到匹配项 有没有办法让我更快地找到匹配项?在最坏的情况下,匹配项是数组中的最后一项。或者接近底部 指纹列表 对不起,关于西班牙语的评论。你可以使用“字典

我的数据库中有一千个指纹存储在一个Byte[]数组中,我正在尝试对指纹进行1:N验证,这意味着我需要比较传感器给出的指纹和数组中的指纹

但是这个过程花费的时间太长了,我正在使用forEach循环迭代数组中的所有指纹,并调用验证方法来比较两个数组以找到匹配项

有没有办法让我更快地找到匹配项?在最坏的情况下,匹配项是数组中的最后一项。或者接近底部

指纹列表


对不起,关于西班牙语的评论。

你可以使用“字典”:

对于每个指纹,您从合适的哈希函数计算一个“long”值,并将指纹存储在与哈希值相关联的列表中(如果无法保证已知指纹之间不会发生冲突,则需要一个列表)

当您想要搜索指纹时,您可以计算散列,从字典中检索相关联的列表,然后按顺序搜索(或使用parallel.foreach)

如果你使用一个合适的散列函数,那么会有几个collison,并且列表大部分都包含一个元素,或者最多包含几个元素,所以顺序搜索不会花费太长时间


注意:即使未知指纹的(散列)列表只包含一个结果,您仍然必须验证实际的字节数组(或提取的特征):指纹很有可能是一个新的指纹,恰好与数据库中的一个指纹产生相同的哈希值。

您可以使用“Dictionary”:

对于每个指纹,您从合适的哈希函数计算一个“long”值,并将指纹存储在与哈希值相关联的列表中(如果无法保证已知指纹之间不会发生冲突,则需要一个列表)

当您想要搜索指纹时,您可以计算散列,从字典中检索相关联的列表,然后按顺序搜索(或使用parallel.foreach)

如果你使用一个合适的散列函数,那么会有几个collison,并且列表大部分都包含一个元素,或者最多包含几个元素,所以顺序搜索不会花费太长时间


注意:即使未知指纹的(散列)列表只包含一个结果,您仍然必须验证实际的字节数组(或提取的特征):指纹很有可能是一个新的指纹,恰好与数据库中的一个指纹产生相同的哈希值。

通过删除不匹配的项目来减少必须搜索的项目数。有很多方法可以做到这一点,但可以举一个例子:

  • 对目标字节数组(要查找的字节)上的每个字节进行交互
  • 在每次迭代中,从源列表中删除项数组中同一索引上的字节与正在迭代的字节不匹配的任何项
  • 这样做,直到你有一个单一的项目
  • 这样,您就不会搜索整个数组,而是一次搜索一个字节并减少搜索的项目数

    如果您想进一步减少此时间,请首先对列表中的字节数组进行排序,并按字典进行搜索。也就是说,只与中间的项目进行比较,然后将列表除以一半,只取你认为匹配的那一半。这样做,直到你只有一个单一项目的一半。这与您尝试在物理词典中搜索单词时所做的相同。首先,你试着打开字典中你想找到的单词的第一个字母;当你找到以这个字母开头的单词时,你试着只找到与你单词的第二个字母相匹配的单词,依此类推。为此,您需要首先对列表进行排序(开头的字节数组为{0,0,0,…},结尾的字节数组为{255,255,…})

    例如,无论数组的长度如何,该算法都只需要将列表中最多16个字节与65536个项进行比较。这会很快


    这只是一个没有任何代码的对话示例,但我想你已经明白了。一种简单的方法是创建一个名为FingerPrint的类来表示字节数组,重写它的GetHashCode()和Equals(),但不能保证完全匹配,而且速度要慢得多方法,只需使用哈希表实例执行搜索。

    通过删除不匹配的项来减少必须搜索的项的数量。有很多方法可以做到这一点,但可以举一个例子:

  • 对目标字节数组(要查找的字节)上的每个字节进行交互
  • 在每次迭代中,从源列表中删除项数组中同一索引上的字节与正在迭代的字节不匹配的任何项
  • 这样做,直到你有一个单一的项目
  • 这样,您就不会搜索整个数组,而是一次搜索一个字节并减少搜索的项目数

    如果您想进一步减少此时间,请首先对列表中的字节数组进行排序,并按字典进行搜索。也就是说,只与中间的项目进行比较,然后将列表除以一半,只取你认为匹配的那一半。这样做,直到你只有一个单一项目的一半。这与您尝试在物理词典中搜索单词时所做的相同。首先,你试着打开字典中你想找到的单词的第一个字母;当你找到以这个字母开头的单词时,你试着只找到与你单词的第二个字母相匹配的单词,依此类推。要使其起作用,您需要首先对列表进行排序(使用
    List<Huellas> ListaHuellas = new List<Huellas>();
    public class Huellas 
    {
        public int idUsuario;
        public Byte[] Huella;
    }
    
    foreach (Huellas h in ListaHuellas) {
        // Por cada huella... la almacenamos en un MemoryStream como arreglo de bytes.
         MemoryStream fingerprintData = new MemoryStream(h.Huella);
         // Creamos una plantilla a partir de esos bytes...
         DPFP.Template templateIterando = new DPFP.Template(fingerprintData);
         // Extraemos las caracteristicas de la plantilla
         DPFP.FeatureSet features = ExtractFeatures(Sample, DPFP.Processing.DataPurpose.Verification);
         // Verificamos que las caracteristicas sean buenas
         if (features != null) {
            // Compare the feature set with our template
             DPFP.Verification.Verification.Result result = new DPFP.Verification.Verification.Result();
             Verificator.Verify(features, templateIterando, ref result);
             // Y vemos si el resultado es valido o no, (verified)
             // Si es verified, significa que el dedo escaneado ya existia en la base de datos.
             if (result.Verified) {
                 MessageBox.Show(new Form { TopMost = true }, "Usuario encontrado: ID " + h.idUsuario);
                 // Por ultimo se cierra el programa.
                 this.Invoke(new MethodInvoker(delegate { this.Close(); })); 
             }
         }
     }