繁体   English   中英

帮助Linq和Dictionary的ContainsKey方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM