linq-Lookup<TKey, TElement>
Lookup<TKey,TElement> 类
定义
表示键的集合,其中每个键映射到一个或多个值。
public class Lookup<TKey,TElement> : System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey,TElement>>, System.Linq.ILookup<TKey,TElement>
- TKey
Lookup<TKey,TElement> 中的键的类型。
- TElement
IEnumerable<T> 中的每个 Lookup<TKey,TElement> 值的元素的类型。
- 继承
-
Lookup<TKey,TElement>
- 实现
-
IEnumerable<IGrouping<TKey,TElement>> IEnumerable ILookup<TKey,TElement>
示例
下面的示例 Lookup<TKey,TElement> 从对象的集合创建。 然后枚举 Lookup<TKey,TElement> 并输出密钥的关联值集合中的每个键和每个值。 它还演示了如何使用属性 Count 和 Item[] 以及方法 Contains 和 GetEnumerator 。
class Package { public string Company; public double Weight; public long TrackingNumber; } public static void LookupExample() { // Create a list of Packages to put into a Lookup data structure. List<Package> packages = new List<Package> { new Package { Company = "Coho Vineyard", Weight = 25.2, TrackingNumber = 89453312L }, new Package { Company = "Lucerne Publishing", Weight = 18.7, TrackingNumber = 89112755L }, new Package { Company = "Wingtip Toys", Weight = 6.0, TrackingNumber = 299456122L }, new Package { Company = "Contoso Pharmaceuticals", Weight = 9.3, TrackingNumber = 670053128L }, new Package { Company = "Wide World Importers", Weight = 33.8, TrackingNumber = 4665518773L } }; // Create a Lookup to organize the packages. Use the first character of Company as the key value. // Select Company appended to TrackingNumber for each element value in the Lookup. Lookup<char, string> lookup = (Lookup<char, string>)packages.ToLookup(p => Convert.ToChar(p.Company.Substring(0, 1)), p => p.Company + " " + p.TrackingNumber); // Iterate through each IGrouping in the Lookup and output the contents. foreach (IGrouping<char, string> packageGroup in lookup) { // Print the key value of the IGrouping. Console.WriteLine(packageGroup.Key); // Iterate through each value in the IGrouping and print its value. foreach (string str in packageGroup) Console.WriteLine(" {0}", str); } // This code produces the following output: // // C // Coho Vineyard 89453312 // Contoso Pharmaceuticals 670053128 // L // Lucerne Publishing 89112755 // W // Wingtip Toys 299456122 // Wide World Importers 4665518773 // Get the number of key-collection pairs in the Lookup. int count = lookup.Count; // Select a collection of Packages by indexing directly into the Lookup. IEnumerable<string> cgroup = lookup['C']; // Output the results. Console.WriteLine("\nPackages that have a key of 'C':"); foreach (string str in cgroup) Console.WriteLine(str); // This code produces the following output: // // Packages that have a key of 'C' // Coho Vineyard 89453312 // Contoso Pharmaceuticals 670053128 // Determine if there is a key with the value 'G' in the Lookup. bool hasG = lookup.Contains('G'); }
注解
Lookup<TKey,TElement>类似于 Dictionary<TKey,TValue> 。 不同之处在于,将 Dictionary<TKey,TValue> 键映射到单个值,而将键 Lookup<TKey,TElement> 映射到值的集合。
您可以 Lookup<TKey,TElement> 通过对实现的对象调用来创建的实例 ToLookup IEnumerable<T> 。
备注
没有公共构造函数来创建的新实例 Lookup<TKey,TElement> 。 此外, Lookup<TKey,TElement> 对象是不可变的,也就是说,创建后,无法在对象中添加或删除元素或键 Lookup<TKey,TElement> 。
属性
Count |
获取 Lookup<TKey,TElement> 中的键/值对集合的数目。 |
Item[TKey] |
获取由指定的键编制索引的值的集合。 |
方法
ApplyResultSelector<TResult>(Func<TKey,IEnumerable<TElement>,TResult>) |
对每个键及其关联值应用转换函数,并返回结果。 |
Contains(TKey) |
确定指定的键是否位于 Lookup<TKey,TElement> 中。 |
Equals(Object) |
确定指定对象是否等于当前对象。 (继承自 Object) |
GetEnumerator() |
返回一个循环访问 Lookup<TKey,TElement> 的泛型枚举数。 |
GetHashCode() |
作为默认哈希函数。 (继承自 Object) |
GetType() |
获取当前实例的 Type。 (继承自 Object) |
MemberwiseClone() |
创建当前 Object 的浅表副本。 (继承自 Object) |
ToString() |
返回表示当前对象的字符串。 (继承自 Object) |
lookup也是一个键值对的集合。不过它是一对多,更像sql里的group by.分组。
看下这个案例:
// Just types covering some different assemblies Type[] sampleTypes = new[] { typeof(List<>), typeof(string), typeof(Enumerable), typeof(XmlReader) }; // All the types in those assemblies IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly) .SelectMany(a => a.GetTypes()); // Grouped by namespace, but indexable ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace); foreach (Type type in lookup["System"]) { Console.WriteLine("{0}: {1}", type.FullName, type.Assembly.GetName().Name); }
----------------------我的分界线=--------------------------------------------
linq中toLookup源码:
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) => ToLookup(source, keySelector, null); public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } if (keySelector == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector); } return Lookup<TKey, TSource>.Create(source, keySelector, comparer); } public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) => ToLookup(source, keySelector, elementSelector, null); public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } if (keySelector == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector); } if (elementSelector == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementSelector); } return Lookup<TKey, TElement>.Create(source, keySelector, elementSelector, comparer); } }
internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer) { Debug.Assert(source != null); Debug.Assert(keySelector != null); Debug.Assert(elementSelector != null); Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer); foreach (TSource item in source) { lookup.GetGrouping(keySelector(item), create: true)!.Add(elementSelector(item)); } return lookup; }
internal Grouping<TKey, TElement>? GetGrouping(TKey key, bool create) { int hashCode = InternalGetHashCode(key); for (Grouping<TKey, TElement>? g = _groupings[hashCode % _groupings.Length]; g != null; g = g._hashNext) { if (g._hashCode == hashCode && _comparer.Equals(g._key, key)) { return g; } } if (create) { if (_count == _groupings.Length) { Resize(); } int index = hashCode % _groupings.Length; Grouping<TKey, TElement> g = new Grouping<TKey, TElement>(key, hashCode); g._hashNext = _groupings[index]; _groupings[index] = g; if (_lastGrouping == null) { g._next = g; } else { g._next = _lastGrouping._next; _lastGrouping._next = g; } _lastGrouping = g; _count++; return g; } return null; }
最下面这个Grouping方法。