代码之家  ›  专栏  ›  技术社区  ›  Soul_Master

如何在C 4.0中修改iLookup对象?

  •  4
  • Soul_Master  · 技术社区  · 15 年前

    在.NET 3.5发布之前,我使用

    Dictionary<TKey, List<TValue>> 
    

    用于包含数据。但我刚刚发现.NET3.5提供了新的集合类型,即iLookup类,它可以表示我以前的复杂数据类型。

    我总是使用Linq扩展方法(ToLookup方法)创建iLookup对象。但我不知道如何修改iLookup对象。

    有可能吗?或者我需要使用union方法创建并再次调用tolookup方法。

    谢谢,

    3 回复  |  直到 8 年前
        1
  •  4
  •   mqp    15 年前

    你没有,这是不变的。您已经列出了两个合理的选项;要么使用子集合的字典,要么继续创建新的查找。

        2
  •  4
  •   Jordan    14 年前

    下面是一个实现 ILookup 这是可以操纵的。它围绕着 Dictionary 属于 List 元素的。它是完全通用的。我想不出更好的名字。:)

    public class LookupDictionary<TKey, TElement> : ILookup<TKey, TElement>
    {
        private Dictionary<TKey, List<TElement>> _dicLookup = new Dictionary<TKey, List<TElement>>();
    
        public LookupDictionary()
        {
    
        }
    
        public LookupDictionary(ILookup<TKey, TElement> a_lookup)
        {
            foreach (var grouping in a_lookup)
            {
                foreach (var element in grouping)
                    AddElement(grouping.Key, element);
            }
        }
    
        public IEnumerable<TElement> AllElements
        {
            get
            {
                return (from key in _dicLookup.Keys
                        select _dicLookup[key])
                        .SelectMany(list => list);
            }
        }
    
        public int Count
        {
            get 
            {
                return AllElements.Count();
            }
        }
    
        public IEnumerable<TElement> this[TKey a_key]
        {
            get 
            {
                List<TElement> list;
                if (_dicLookup.TryGetValue(a_key, out list))
                    return list;
    
                return new TElement[0];
            }
        }
    
        public bool Contains(TKey a_key)
        {
            return _dicLookup.ContainsKey(a_key);
        }
    
        public void Add(TKey a_key, TElement a_element)
        {
            AddElement(a_key, a_element);
        }
    
        public void RemoveKey(TKey a_key)
        {
            _dicLookup.Remove(a_key);
        }
    
        public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
        {
            return GetGroupings().GetEnumerator();
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (GetGroupings() as System.Collections.IEnumerable).GetEnumerator();
        }
    
        private void AddElement(TKey a_key, TElement a_element)
        {
            List<TElement> list;
    
            if (!_dicLookup.TryGetValue(a_key, out list))
            {
                list = new List<TElement>();
                _dicLookup.Add(a_key, list);
            }
    
            list.Add(a_element);
        }
    
        private IEnumerable<IGrouping<TKey, TElement>> GetGroupings()
        {
            return from key in _dicLookup.Keys
                   select new LookupDictionaryGrouping<TKey, TElement>
                   {
                       Key = key,
                       Elements = _dicLookup[key]
                   } as IGrouping<TKey, TElement>;
        }
    }
    
    public class LookupDictionaryGrouping<TKey, TElement> : IGrouping<TKey, TElement>
    {
        public TKey Key
        {
            get;
            set;
        }
    
        public IEnumerable<TElement> Elements
        {
            get;
            set;
        }
    
        public IEnumerator<TElement> GetEnumerator()
        {
            return Elements.GetEnumerator();
        }
    
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (Elements as System.Collections.IEnumerable).GetEnumerator();
        }
    }
    
        3
  •  0
  •   Sorensen    8 年前

    正如mquander提到的,查找是不可变的。但是,可以使用附加值或删除的值构建新的查找。

    // Add a new value
    myLookup = myLookup
        .SelectMany(l => l.Select(v => new {l.Key, Value = v}))
        .Union(new[] {new {Key = myNewKey, Value = myNewValue}})
        .ToLookup(a => a.Key, a => a.Value);
    
    // Remove an old value
    myLookup = myLookup
        .SelectMany(l => l.Select(v => new {l.Key, Value = v}))
        .Where(a => a.Value != myOldValue)
        .ToLookup(a => a.Key, a => a.Value);
    
    推荐文章