迭代1000个元素

时间:2017-08-18 19:28:07

标签: c# list optimization foreach fingerprint

我的数据库中有一千个指纹存储在Byte []数组中,我试图对指纹进行1到N的验证,这意味着我需要比较传感器给出的指纹以及数组中的那些。

但是这个过程耗时太长,我使用forEach循环遍历数组中的所有指纹并调用验证方法来比较2个数组以找到匹配。

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

指纹列表

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

对不起&#39;关于西班牙语的评论。

3 个答案:

答案 0 :(得分:2)

你可以使用'Dictionary&lt;长,列表&lt; Huellas&GT;&GT;':

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

如果要搜索指纹,可以计算哈希值,从字典中检索关联列表,然后可以按顺序搜索(或使用parallel.foreach)。

如果你使用一个不错的哈希函数,那么将会有很少的collisons,这些列表将主要包含一个元素或者最多只包含一个元素,因此顺序搜索不会花费很长时间。

注意:即使未知指纹的(散列)列表只包含一个结果,您仍然需要验证实际的字节数组(或提取的功能):指纹实际上总是存在的可能性新的,恰好产生与数据库中的一个指纹相同的哈希。

答案 1 :(得分:0)

删除那些永远不会匹配的项目,减少必须搜索的项目数。有很多方法可以做到这一点,但一个例子可能是:

  1. 对目标字节数组(您要查找的那个)上的每个字节进行交互。
  2. 在每次迭代中,删除源列表中的任何条目,其中item数组上相同索引上的字节与您正在迭代的字节不匹配。
  3. 直到您有一个项目为止。
  4. 这样,您不是在搜索整个数组,而是一次搜索一个字节并减少搜索项目的数量。

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

    例如,无论数组的长度如何,该算法都需要在列表中最多比较16个字节和65536个项目。这将非常快。

    这只是一个没有任何代码的谈话示例,但我认为你有了这个想法。一个简单的方法,但没有完美匹配和更慢的保证将创建一个名为FingerPrint的类表示字节数组,覆盖其GetHashCode()和Equals()方法,只需使用 HashTable < / strong>实例执行搜索。

答案 2 :(得分:0)

我的问题是我每次迭代forEach循环时都会提取传感器给出的样本指纹的特征。感谢ainwood的评论,我将特征提取移到了循环外部,因为我只需要提取一次样本的特征,并与List中的指纹进行比较,并将最坏情况从15秒减少到2。 / p>