2009-07-27 8 views
5

현재이 사전 변수에 저장된 하위 항목이있는 메뉴가 있습니다.여러 개의 키를 허용하는 Dictionary <string, object> 컬렉션이 있습니까?

private Dictionary<string, UserControl> _leftSubMenuItems 
    = new Dictionary<string, UserControl>(); 

"고객"섹션은 다음과 같습니다.

_leftSubMenuItems.Add("customers", container.Resolve<EditCustomer>()); 
_leftSubMenuItems.Add("customers", container.Resolve<CustomerReports>()); 

그러나 사전을 사용하고 있으므로 는 "customers"라는 하나의 키만 가질 수 있습니다.

내 자연적인 경향은 이제 "단면도"와 "보기"속성이있는 사용자 지정 구조체를 만드는 것이지만 은 .NET 컬렉션이 "MultiKeyDictionary"와 같은이 작업에 더 적합합니까?

답변 :

덕분에 maciejkow, 내가 필요로 정확하게 얻을 수 있도록 제안을 확장 :

using System; 
using System.Collections.Generic; 

namespace TestMultiValueDictionary 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MultiValueDictionary<string, object> leftSubMenuItems = new MultiValueDictionary<string, object>(); 

      leftSubMenuItems.Add("customers", "customers-view1"); 
      leftSubMenuItems.Add("customers", "customers-view2"); 
      leftSubMenuItems.Add("customers", "customers-view3"); 
      leftSubMenuItems.Add("employees", "employees-view1"); 
      leftSubMenuItems.Add("employees", "employees-view2"); 

      foreach (var leftSubMenuItem in leftSubMenuItems.GetValues("customers")) 
      { 
       Console.WriteLine(leftSubMenuItem); 
      } 

      Console.WriteLine("---"); 

      foreach (var leftSubMenuItem in leftSubMenuItems.GetAllValues()) 
      { 
       Console.WriteLine(leftSubMenuItem); 
      } 

      Console.ReadLine(); 
     } 
    } 

    public class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>> 
    { 

     public void Add(TKey key, TValue value) 
     { 
      if (!ContainsKey(key)) 
       Add(key, new List<TValue>()); 
      this[key].Add(value); 
     } 

     public List<TValue> GetValues(TKey key) 
     { 
      return this[key]; 
     } 

     public List<TValue> GetAllValues() 
     { 
      List<TValue> list = new List<TValue>(); 

      foreach (TKey key in this.Keys) 
      { 
       List<TValue> values = this.GetValues(key); 
       list.AddRange(values); 
      } 

      return list; 
     } 
    } 

} 
이 답변

: 여기, 수율에 대한 팁을위한

감사 Blixt 것은 GetAllValues입니다 그 변화와 함께 :

public IEnumerable<TValue> GetAllValues() 
{ 
    foreach (TKey key in this.Keys) 
    { 
     List<TValue> values = this.GetValuesForKey(key); 
     foreach (var value in values) 
     { 
      yield return value; 
     } 
    } 
} 

답변 2 리팩터링 더 :

다음과 같은 일을 훨씬 더 간결한 방법, 감사합니다 키이스 :

public IEnumerable<TValue> GetAllValues() 
{ 
    foreach (var keyValPair in this) 
     foreach (var val in keyValPair.Value) 
      yield return val; 
} 
+1

당신의'GetAllValues' 메쏘드에 대해 새로운 목록을 생성하는 대신'yield' 키워드를 사용할 수 있습니다.이 목록은 더 많은 메모리를 사용하며 덜 효율적입니다. – Blixt

+0

그게 전부일지도 모르지만 그것의 거의 완전한 다국어. '제거 '는 어떨까요? 값을 열거 하시겠습니까? –

+1

실제로 적절한 해결책은 바퀴를 재발 명하지 않고 답변에 링크 된 라이브러리 중 하나를 사용하거나 필요한 것을 더하는 다른 것을 찾아 보는 것입니다. 이러한 일반적인 목적을 위해 잘 테스트되고 최적화 된 것을 찾으십시오. – Blixt

답변

10

당신은 하나의 키 값의 변수 번호가 필요하면 왜 안 Dictionary<string, List<UserControl>>을 만들? 또한,이 클래스를 상속 받아 자신 만의 Add를 만들 수도 있습니다. 지금 사용하고있는 것과 동일한 구문을 얻을 수 있습니다.이렇게하면 새 컨트롤을 추가하기 전에 빈 목록을 수동으로 추가하지 않아도됩니다. 이 같은

STH :

class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>> 
{ 

    public void Add(TKey key, TValue value) 
    { 
     if(!ContainsKey(key)) 
     Add(key, new List<TValue>()); 
     this[key].Add(value); 
    } 
} 
+0

http://stackoverflow.com/questions/1187219/is-there-a-dictionarystring-object-collection-which-allows-multiple-keys/1187252#1187252에서 참조 된 디버깅 된 디버거가 있습니까? –

1

아니, 더 좋은가 내장되지-에 소장. 나는 당신의 "자연적인 경향"이이 문제를 해결하는데 완벽하다고 생각합니다. 그것들은 실제로 "같은 열쇠"가 아니지만 서로 다른 부분으로 구성된 유일한 열쇠이며 Dictionary이 그 일을합니다. 당신은 할 수도 둥지 사전 (각 이름에 대한 값의 수가 많은 경우 의미가 있습니다) :

Dictionary<string, Dictionary<Type, object>> dict = ...; 
var value = (T)dict[name][typeof(T)]; 

이 방법은 하나의 해시 테이블 조회를 사용하여 요소에 해결됩니다. 각 요소에 대한 항목 목록을 유지 관리 할 경우 먼저 Dictionary을 사용하는 목적을 상실한 요소를 조회 할 때마다 목록을 선형 적으로 탐색해야합니다.

0

"MultiKeyDictionary"에 대해 알지 못합니다. 구조체를 사용하고 GetHashCode, Equals 및 IEquatable < StructName> (Dictionary < TKey, TValue>에서 사용하는)을 재정의하는 것이 좋습니다.

4

어떻게 용기 값 목록을 입력하고 약 :

private Dictionary<string, List<UserControl>> _leftSubMenuItems = 
    new Dictionary<string, List<UserControl>>(); 

if (!_leftSubMenuItems.ContainsKey("customers")) 
{ 
    _leftSubMenuItems["customers"] = new List<UserControl>(); 
} 
_leftSubMenuItems["customers"].Add(container.Resolve<EditCustomer>()); 
_leftSubMenuItems["customers"].Add(container.Resolve<CustomerReports>()); 
5

체크 아웃 NGenerics 'HashList을. 각 키의 값 목록을 유지 관리하는 사전입니다. Wintellect's PowerCollections 라이브러리에는 또한 주어진 키와 관련된 마지막 값을 제거 할 때 자동으로 정리하는 것과 같은 일을하는 편리한 MultiDictionary 클래스가 있습니다.

+0

+1 : 내가 제안한 것을 자연스럽게 수행 할 수있는 래퍼. – Blixt

0

당신은 함께 키에 여러 항목을 저장하기 위해 찾고 계십니까? 좀 this 같은 모양?

불과 몇 개조하면 되겠
3

...

public class MultiValueDictionary<TKey, TValue> : 
    Dictionary<TKey, List<TValue>> 
{ 

    public void Add(TKey key, TValue value) 
    { 
     List<TValue> valList; 
     //a single TryGetValue is quicker than Contains then [] 
     if (this.TryGetValue(key, out valList)) 
      valList.Add(value); 
     else 
      this.Add(key, new List<TValue> { value }); 
    } 

    //this can be simplified using yield 
    public IEnumerable<TValue> GetAllValues() 
    { 
     //dictionaries are already IEnumerable, you don't need the extra lookup 
     foreach (var keyValPair in this) 
      foreach(var val in keyValPair.Value); 
       yield return val; 
    } 
} 
+0

+ +1'yield'에 +1하지만, 여전히 확실하게 여러 개의 다른 것들 ('MultiValueDictionary'에서 기대할 수있는 모든 기능을 갖춤)이있을 때 나 자신의 래퍼를 구현하는 데 심히 많은 시간을 소비했다고 믿고 있지만, 많은 사용자가 테스트했습니다. – Blixt

+0

GetAllValues ​​()를 다음과 같이 단순화 할 수 있습니다. public IEnumerable GetAllValues ​​() { return this.SelectMany (keyValPair => keyValPair.Value); }' – Kaboo

1

닷넷 프레임 워크 3.5은 특별한 LINQ Lookup 클래스가 포함되어 있습니다.

동일한 키를 사용하여 여러 항목을 처리 할 수 ​​있다는 점을 제외하면 사전과 유사합니다. 주어진 키를 사용하여 검색을 수행하면 단일 요소를받는 대신 해당 키와 일치하는 요소 그룹이 수신됩니다.

나는 그것이 검색을 위해 빠르므로 커버 아래의 해시 테이블이라는 것을 읽었습니다.

당신은 이런 식으로 뭔가를 사용 :

  • 당신은 단지 조회 객체를 생성 캔트 있도록 조회 클래스는 공용 생성자가 없습니다, 그것은 것 같다

    var example1 = (from element in ListWithDuplicates 
          select element) 
          .ToLookup(A => A.Name); 
    

    는주의의 무리가 있습니다 .ToLookup 구문을 통해서만 사용할 수 있습니다.

  • 당신이 생성되면, 더 추가 편집하거나 제거 할 수없는 등
  • 은 분명히 그는

까다로운 조금 할 수 있습니다 그룹화 된 데이터를 사용하여

  • 직렬화 할 수없는 조회를 논의 great article here Theres는 그 의미에 대해 좀 더 자세히 설명합니다.

  • 관련 문제