linq-Lookup<TKey, TElement>


Lookup

定义

命名空间:
System.Linq
程序集:
netstandard.dll

表示键的集合,其中每个键映射到一个或多个值。

public class Lookup : System.Collections.Generic.IEnumerable>, System.Linq.ILookup
类型参数
TKey

Lookup 中的键的类型。

TElement

IEnumerable 中的每个 Lookup 值的元素的类型。

继承
Object Lookup
实现
IEnumerable>  IEnumerable  ILookup

示例

下面的示例 Lookup 从对象的集合创建。 然后枚举 Lookup 并输出密钥的关联值集合中的每个键和每个值。 它还演示了如何使用属性 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 packages = new List { 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类似于 Dictionary 。 不同之处在于,将 Dictionary 键映射到单个值,而将键 Lookup 映射到值的集合。

您可以 Lookup 通过对实现的对象调用来创建的实例 ToLookup IEnumerable 。

 备注

没有公共构造函数来创建的新实例 Lookup 。 此外, Lookup 对象是不可变的,也就是说,创建后,无法在对象中添加或删除元素或键 Lookup 。

属性

属性
Count

获取 Lookup 中的键/值对集合的数目。

Item[TKey]

获取由指定的键编制索引的值的集合。

方法

方法
ApplyResultSelector(Func,TResult>)

对每个键及其关联值应用转换函数,并返回结果。

Contains(TKey)

确定指定的键是否位于 Lookup 中。

Equals(Object)

确定指定对象是否等于当前对象。

(继承自 Object)
GetEnumerator()

返回一个循环访问 Lookup 的泛型枚举数。

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 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 ToLookup(this IEnumerable source, Func keySelector) =>
            ToLookup(source, keySelector, null);
 
        public static ILookup ToLookup(this IEnumerable source, Func keySelector, IEqualityComparer? comparer)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }
 
            if (keySelector == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector);
            }
 
            return Lookup.Create(source, keySelector, comparer);
        }
 
        public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector) =>
            ToLookup(source, keySelector, elementSelector, null);
 
        public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? comparer)
        {
            if (source == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
            }
 
            if (keySelector == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector);
            }
 
            if (elementSelector == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementSelector);
            }
 
            return Lookup.Create(source, keySelector, elementSelector, comparer);
        }
    }
        internal static Lookup Create(IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer? comparer)
        {
            Debug.Assert(source != null);
            Debug.Assert(keySelector != null);
            Debug.Assert(elementSelector != null);
 
            Lookup lookup = new Lookup(comparer);
            foreach (TSource item in source)
            {
                lookup.GetGrouping(keySelector(item), create: true)!.Add(elementSelector(item));
            }
 
            return lookup;
        }
       internal Grouping? GetGrouping(TKey key, bool create)
        {
            int hashCode = InternalGetHashCode(key);
            for (Grouping? 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 g = new Grouping(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方法。