如何有效地比较两个列表与500k对象和字符串

时间:2015-04-01 07:09:32

标签: c# asp.net asp.net-mvc linq

所以我有一个带有子文件夹和大约500k图像的主目录。我知道我的数据库中不存在很多theese图像,我想知道哪些图像可以删除它们。

这是我到目前为止的代码:

var listOfAdPictureNames = ImageDB.GetAllAdPictureNames();

var listWithFilesFromImageFolder = ImageDirSearch(adPicturesPath);

var result = listWithFilesFromImageFolder.Where(p => !listOfAdPictureNames.Any(q => p.FileName == q));

var differenceList = result.ToList();

listOfAdPictureNames的类型为List<string>

这是我从ImageDirSearch中退出的模型:

public class CheckNotUsedAdImagesModel
{
    public List<ImageDirModel> ListWithUnusedAdImages { get; set; }
}

public class ImageDirModel
{
    public string FileName { get; set; }
    public string Path { get; set; }
}

这是从我的文件夹中获取所有图像的递归方法。

private List<ImageDirModel> ImageDirSearch(string path)
        {
            string adPicturesPath = ConfigurationManager.AppSettings["AdPicturesPath"];
            List<ImageDirModel> files = new List<ImageDirModel>();

try
{
    foreach (string f in Directory.GetFiles(path))
    {
        var model = new ImageDirModel();
        model.Path = f.ToLower();
        model.FileName = Path.GetFileName(f.ToLower());
        files.Add(model);
    }
    foreach (string d in Directory.GetDirectories(path))
    {
        files.AddRange(ImageDirSearch(d));
    }
}
catch (System.Exception excpt)
{
    throw new Exception(excpt.Message);
}

return files;

}

我遇到的问题是这一行:

var result = listWithFilesFromImageFolder.Where(p => !listOfAdPictureNames.Any(q => p.FileName == q));

需要一个多小时才能完成。我想知道是否有更好的方法来检查我的images文件夹中是否存在我的数据库中不存在的图像。

以下是从我的数据库层获取所有图像名称的方法:

    public static List<string> GetAllAdPictureNames()
    {
        List<string> ListWithAllAdFileNames = new List<string>();

        using (var db = new DatabaseLayer.DBEntities())
        {
            ListWithAllAdFileNames = db.ad_pictures.Select(b => b.filename.ToLower()).ToList();
        }



        if (ListWithAllAdFileNames.Count < 1)
            return new List<string>();

        return ListWithAllAdFileNames;
    }

3 个答案:

答案 0 :(得分:1)

或许Except正是您所寻找的。像这样:

var filesInFolderNotInDb = listWithFilesFromImageFolder.Select(p => p.FileName).Except(listOfAdPictureNames).ToList();

应该为您提供文件夹中但不在数据库中的文件。

答案 1 :(得分:0)

正如我在评论中所说,您似乎已经重新创建了FileInfo课程,您不需要这样做,因此您的ImageDirSearch可以成为以下

private IEnumerable<string> ImageDirSearch(string path)
{
    return Directory.EnumerateFiles(path, "*.jpg", SearchOption.TopDirectoryOnly);
}

通过返回只需要文件名的整个文件信息似乎没有多少收获,而且这只能找到jpgs,但这可以改变..

ToLower调用非常昂贵并且有点无意义,当您计划再次查询时列出的内容也是如此,以便您可以摆脱它并再次返回IEnumerable(这是在GetAllAdPictureNames方法中)

然后你的比较可以使用equals并忽略大小写。

!listOfAdPictureNames.Any(q => p.Equals(q, StringComparison.InvariantCultureIgnoreCase));

可能有帮助的另一件事就是从文件名列表中删除项目,这样可以在每次删除文件时更快地搜索列表,因为迭代次数较少。

答案 2 :(得分:0)

不是在每个列表上重复搜索,而是对第二个列表“listOfAdPictureNames”(使用n * log(n)排序中的任何一个)进行排序。然后通过二分搜索检查存在将是所有其他技术中最有效的,包括当前的顺序是指数的。