[英]Help with Linq and Dictionary's ContainsKey method
我正在编写一个工具,该工具的第一部分是在我们的公共API中收集所有头文件。 问题是,两个头文件具有重复的文件名(但它们位于不同的文件夹中)。 创建字典时,这将导致问题。
最初,我编写了一个foreach循环来将FileInfo实例收集到字典中。 但是最近我正在学习LINQ,并且想将foreach循环转换为LINQ语句。 问题是当它执行时,它抱怨文件名重复。
这是原始代码:
public Dictionary<String, FileDependency> GetSDKFiles(DirectoryInfo dir)
{
Dictionary<String, FileDependency> list = new Dictionary<String, FileDependency>();
foreach (FileInfo info in dir.EnumerateFiles("*.h", SearchOption.AllDirectories))
{
String key = info.Name.ToLower();
if (list.ContainsKey(key) == false)
{
list.Add(key, new FileDependency(info.FullName));
}
else
{
Debug.Print("Duplicate key: {0}", info.Name);
Debug.Print(" File: {0}", info.FullName);
Debug.Print(" Have: {0}", list[key].FullFileName);
}
}
return list;
}
我试图像这样变成LINQ:
public Dictionary<String, FileDependency> GetSDKFilesLINQ(DirectoryInfo dir)
{
var files = from info in dir.EnumerateFiles("*.h", SearchOption.AllDirectories)
let key = info.Name.ToLower()
let dep = new FileDependency(info.FullName)
select new { key, dep };
return files.ToDictionary(v => v.key, v => v.dep);
}
但是在运行时我得到了:
具有相同键的项目已被添加。
在foreach循环中,避免这种情况很容易,因为我调用了ContainsKey方法来确保没有重复项。 但是,LINQ等效项是什么?
我在哪里使用? - 怎么样? 我使用小组吗? - 怎么样?
谢谢。
var files = dir.EnumerateFiles("*.h", SearchOption.AllDirectories)
.GroupBy(file => file.Name.ToLower())
.Select(group => new {Key = group.Key, Value = group.First()})
.ToDictionary(a => a.Key, a => new FileDependency (a.Value.FullName));
如果您有MoreLinq ,则可以执行以下操作:
var files = dir.EnumerateFiles("*.h", SearchOption.AllDirectories)
.DistinctBy(file => file.Name.ToLower())
.ToDictionary(file => new FileDependency (a.Value.FullName));
另外,您可以为文件编写自己的IEqualityComparer
实现,并使用标准的Distinct
方法。 这里的整个问题是Distinct
(至少从.NET 3.5开始)没有重载,该重载允许您将自己的“区别性”定义插入为lambda表达式。
您可以按键分组并从分组中获取第一个值作为dep:
public Dictionary<String, FileDependency> GetSDKFilesLINQ(DirectoryInfo dir)
{
var files = from info in dir.EnumerateFiles(
"*.h", SearchOption.AllDirectories)
let key = info.Name.ToLower()
let dep = new FileDependency(info.FullName)
group dep by key into g
select new { key = g.Key, dep = g.First() };
return files.ToDictionary(v => v.key, v => v.dep);
}
那将默默地忽略重复项。 或者,您可以使用Lookup而不是Dictionary:
public ILookup<String, FileDependency> GetSDKFilesLINQ2(DirectoryInfo dir)
{
var files = from info in dir.EnumerateFiles(
"*.h", SearchOption.AllDirectories)
let key = info.Name.ToLower()
let dep = new FileDependency(info.FullName)
select new { key, dep };
return files.ToLookup(v => v.key, v => v.dep);
}
查找上的索引器将返回IEnumerable<FileDependency>
,因此您可以看到所有值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.