C# C将一个列表与另一个列表的一部分进行比较
我正在尝试从网站上删除不需要的图像。产品图像文件夹包含超过200000个图像。我有一个列表中不活动的产品代码列表。我在另一个列表中有文件名列表C# C将一个列表与另一个列表的一部分进行比较,c#,performance,linq,loops,C#,Performance,Linq,Loops,我正在尝试从网站上删除不需要的图像。产品图像文件夹包含超过200000个图像。我有一个列表中不活动的产品代码列表。我在另一个列表中有文件名列表 List<string> lFileList = files.ToList(); List<string> lNotinfiles = new List<string>(); foreach (var s in lFileList) { var s2 = (from s3 in lProductsList
List<string> lFileList = files.ToList();
List<string> lNotinfiles = new List<string>();
foreach (var s in lFileList)
{
var s2 = (from s3 in lProductsList
where s.Contains(s3.cProductCode)
select s3.cProductCode).FirstOrDefault();
if (s2 == null)
{
lNotinfiles.Add(s);
}
}
我试着一起移除同样不起作用的循环
更快实现这一目标的最佳方式应该是什么 我建议:使用HashSet,和ToList一起等待,也许还有GroupBy
HashSet+使用ToList
目前,代码的时间复杂度为on2—您迭代外部列表,并为每个项目迭代内部列表的所有项目
将LPProductsList的类型从列表更改为包含代码的哈希集。在HashSet中查找项是o1列表中的一项是启用的。然后,当您迭代lFileList的每一次以确定它们是否在lProductsList中时,它的时间复杂度将是on而不是on2
此代码将显示使用2个列表或使用列表和哈希集之间的时间差:
var items = (new[] { "1", "2", "3","4","5","6","7","8","9","10" }).SelectMany(x => Enumerable.Repeat(x, 10000)).ToList();
var itemsToFilterOut = new List<string> { "1", "2", "3" };
var efficientItemsToFilterOut = new HashSet<string>(itemsToFilterOut);
var watch = System.Diagnostics.Stopwatch.StartNew();
var unwantedItems = items.Where(item => itemsToFilterOut.Contains(item)).ToList();
watch.Stop();
Console.WriteLine(watch.TotalMilliseconds);
watch = Stopwatch.StartNew();
var efficientUnwantedItems = items.Where(item => efficientItemsToFilterOut.Contains(item)).ToList();
watch.Stop();
Console.WriteLine(watch.TotalMilliseconds);
群比
此外,您说过列表包含多个映射到同一个键的项。在筛选出之前使用GroupBy。检查此添加项的性能:
watch = Stopwatch.StartNew();
var moreEfficientUnwantedItems = items.GroupBy(item => item)
.Where(group => efficientItemsToFilterOut.Contains(group.Key))
.Select(group => group.Key);
watch.Stop();
Console.WriteLine(watch.TotalMilliseconds);
检查您的数据以分析它的重复量有多大,如果需要,请使用GroupBy您正在将I assumearray转换为列表,然后执行foreach 直接在阵列上使用应该会使它至少快一点
List<string> lNotinfiles = new List<string>();
for(int i = 0; i < files.Count(); i++)
foreach (var s in files)
{
var s2 = (from s3 in lProductsList where s.Contains(s3.cProductCode) select s3.cProductCode).FirstOrDefault();
if (s2 == null)
{
lNotinfiles.Add(s);
}
}
两项建议:
不要具体化文件。ToList,即不要等到检索到所有文件
将NotInFiles组织为哈希集,使其具有更好的竞争力O1而不是ON。
大概是这样的:
//TODO: you have to implement this
prtivate static String ExtractProductCode(string fileName) {
int p = fileName.IndexOf('_');
if (p >= 0)
return fileName.SubString(0, p);
else
return fileName;
}
在这种情况下,watch.appead.totalMillimesons是访问ElapsedMillimesons的更好属性,因为TotalMillimesons是双精度,而ElapsedMillimesons是长型,将被舍入。没问题,仅供参考,ElapsedTicks也将遭受同样的命运,因为它也是一个长或int64。请确保在测量代码时在后面列出。选择:延迟执行将使您在代码段中达到目标。谢谢,是的,为了理解此问题。。。我无法测试它,因为我确实有时间做那个项目。
List<string> lNotinfiles = new List<string>();
for(int i = 0; i < files.Count(); i++)
foreach (var s in files)
{
var s2 = (from s3 in lProductsList where s.Contains(s3.cProductCode) select s3.cProductCode).FirstOrDefault();
if (s2 == null)
{
lNotinfiles.Add(s);
}
}
//TODO: you have to implement this
prtivate static String ExtractProductCode(string fileName) {
int p = fileName.IndexOf('_');
if (p >= 0)
return fileName.SubString(0, p);
else
return fileName;
}
HashSet<String> NotInFiles = new HashSet<String>(
lNotinfiles,
StringComparer.OrdinalIgnoreCase); // file names are case insensitive
var files = Directory
.EnumerateFiles(@"C:\MyPictures", "*.jpeg", SearchOption.AllDirectories)
.Where(path => Path.GetFileNameWithoutExtension(path))
.Select(path => ExtractProductCode(path))
.Where(code => !NotInFiles.Contains(code))
.ToList(); // if you want List materialization