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>
实现

示例

下面的示例 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方法。

 

posted @ 2021-11-18 17:07  vba是最好的语言  阅读(79)  评论(0编辑  收藏  举报