初始化Lookup
如何在c#中的对象初始化程序例程中为属性声明一个新的查找类?
例如
new Component() { ID = 1, Name = "MOBO", Category = new Lookup }
类别位总是会出现编译错误。
我有一个名为Category
的属性,其类型为Lookup
,我希望通过实例化此属性
new Component() { ID = 1, Name = "MOBO", Category = new Lookup };
但我无法克服编译错误。
根据MSDN文档, Lookup
类没有公共构造函数: http : //msdn.microsoft.com/en-us/library/bb460184.aspx
您可以通过在实现IEnumerable
的对象上调用ToLookup
来创建Lookup
的实例。
你会想做类似的事情:
new Component { ID = 1, Name = "MOBO", Category = new[] { … }.ToLookup(…) }
更新以发表评论:
我不确定你从哪里获得类别信息,所以我会做些什么……
new Component { ID = 1, Name = "MOBO", Category = new Dictionary { { 3, "Beverages" } { 5, "Produce" } }.ToLookup(o => o.Key, o => o.Value) }
我的猜测是你的类别将来自其他来源,而不是像我在这里实例化的字典。
来自MSDN :
没有公共构造函数来创建Lookup
的新实例。
此外, Lookup
对象是不可变的,也就是说,在创建后,您无法在Lookup
对象中添加或删除元素或键。
你不能只使用ToLookup; 你必须告诉它如何找到键和值:
// from ChaosPandion's code using System.Linq; // make sure you have the using statement var component = new Component() { ID = 1, Name = "MOBO", Category = (Lookup) (new Dictionary() { {1, "one"} }) .ToLookup(p=>p.Key, p=>p.Value) }
我不明白你为什么要在这里使用Lookup而不是字典。
这是我对此的尝试。 确保密钥是不可变的( Gist )。
public class MultiValueDictionary : Collection, ILookup { public MultiValueDictionary(Func keyForItem) : base(new Collection(keyForItem)) { } new Collection Items => (Collection)base.Items; public IEnumerable this[TKey key] => Items[key]; public bool Contains(TKey key) => Items.Contains(key); IEnumerator> IEnumerable>.GetEnumerator() => Items.GetEnumerator(); class Collection : KeyedCollection, IEnumerable , IList { Func KeyForItem { get; } public Collection(Func keyForItem) => KeyForItem = keyForItem; protected override TKey GetKeyForItem(Grouping item) => item.Key; public void Add(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection)) collection.Add(item); else Add(new Grouping(key) { item }); } public bool Remove(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection) && collection.Remove(item)) { if (collection.Count == 0) Remove(key); return true; } return false; } IEnumerator IEnumerable .GetEnumerator() { foreach (var group in base.Items) foreach (var item in group) yield return item; } const string IndexError = "Indexing not supported."; public int IndexOf(TElement item) => throw new NotSupportedException(IndexError); public void Insert(int index, TElement item) => Add(item); public bool Contains(TElement item) => Items.Contains(item); public void CopyTo(TElement[] array, int arrayIndex) => throw new NotSupportedException(IndexError); new IEnumerable Items => this; public bool IsReadOnly => false; TElement IList .this[int index] { get => throw new NotSupportedException(IndexError); set => throw new NotSupportedException(IndexError); } } class Grouping : Collection , IGrouping { public Grouping(TKey key) => Key = key; public TKey Key { get; } } }
查找使用与字典相同的概念,不同之处在于字典将键映射到单个值 ,而查找映射是许多值的键 。
这也意味着:
ILookup
可以看作:
IDictionary>
当您想要将许多对象/值映射到同一个键时,您基本上想要使用ILookup
。 您可以从任何对象列表构建ILookup
,您可以通过某些属性对这些对象进行分组。 看到:
public class Product { public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } var products = new List(); products.Add(new Product { Name = "TV", Price = 400, Category = "Electronics" }); products.Add(new Product { Name = "Computer", Price = 900, Category = "Electronics" }); products.Add(new Product { Name = "Keyboard", Price = 50, Category = "Electronics" }); products.Add(new Product { Name = "Orange", Price = 2, Category = "Fruits" }); products.Add(new Product { Name = "Grape", Price = 3, Category = "Fruits" }); // group by category ILookup lookup = products.ToLookup(prod => prod.Category); foreach (var item in lookup) { // this first loop would run two times // because there are two categories: Electronics and Fruits string category = item.Key; decimal totalPriceForCategory = item.Sum(i => i.Price); foreach (var product in item) { // for the electronics, this would loop three times // for the fruits, this would loop two times string name = product.Name; decimal price = product.Price; } }
您还可以获得以下类别的所有产品:
IEnumerable eletronics = lookup["Electronics"]; IEnumerable fruits = lookup["Fruits"];