Lookup ()과 Dictionary (Of list ())의 차이점


165

어떤 데이터 구조가 가장 효율적인지, 언제 어디에서 어떤 데이터 구조를 사용 해야하는지 내 머리를 감싸려고합니다.

이제 구조를 충분히 이해하지 못했을 수도 있지만 어떻게 ILookup(of key, ...)다른 Dictionary(of key, list(of ...))가요?

또한 어디에서 사용하고 싶고 ILookup프로그램 속도 / 메모리 / 데이터 액세스 등의 측면에서 더 효율적입니까?


답변:


255

두 가지 중요한 차이점 :

  • Lookup불변입니다. Yay :) (적어도 구체적인 Lookup클래스는 불변이고 ILookup인터페이스는 변경 멤버를 제공하지 않습니다. 물론 다른 변경 가능한 구현 이 있을 수 있습니다.)
  • 조회에없는 키를 조회하면 KeyNotFoundException. 대신 빈 시퀀스가 ​​다시 나타납니다 . 따라서 TryGetValueAFAICR 은 없습니다 .

그것들은 효율성면에서 동등 할 것 Dictionary<TKey, GroupingImplementation<TValue>>입니다. 예를 들어, 룩업은 배후에서 잘 사용할 수 있습니다 . 요구 사항에 따라 둘 중에서 선택하십시오. 개인적으로 조회는 일반적으로 Dictionary<TKey, List<TValue>>위의 처음 두 지점으로 인해 보다 낫습니다 .

구현 세부 사항으로, 구체적인 구현은 IGrouping<,>값 구현 IList<TValue>에 사용됩니다 Count(). ElementAt()즉와 함께 사용하는 것이 효율적임을 의미합니다 .


존재하지 않는 키 조회로 인해 예외가 아닌 빈 시퀀스가 ​​발생하면 범용 콜렉션 imo로 사용할 수 없습니다. linq 쿼리의 부산물 인 불변 컬렉션이있는 경우 다소 괜찮습니다.
nawfal

@nawfal-이것이 바로 Lookups의 목적입니다. 에서 MSDN : "당신은 객체가 구현을 IEnumerable <T>에 ToLookup을 호출하여 조회 <TKEY, TElement>의 인스턴스를 만들 수 있습니다."
Niall Connaughton

50

아무도 실제로 가장 큰 차이점을 언급하지 않았다는 점에 흥미가 있습니다 ( MSDN 에서 직접 가져옴 )

조회는 사전과 유사합니다. 차이점은 Dictionary는 키를 단일 값에 매핑하고 Lookup은 키를 값 모음에 매핑한다는 것입니다.


51
질문을 확인하십시오 : Lookup <TKey, TValue>와 Dictionary <TKey, List <TValue >>의 차이점에 관한 것이므로 차이점은 이미 명시 적으로 있습니다.
Martao 2016 년

5
@Martao 일부 사람들은 인터넷 검색에서 조회와 사전의 차이점을 이해하기 위해이 질문을 찾습니다. 이 답변은 정말 유용합니다.
jakubiszon

34

a Dictionary<Key, List<Value>>Lookup<Key, Value>논리적으로 데이터를 유사한 방식으로 구성 할 수 있으며 둘 다 동일한 순서로 효율성을 갖습니다. 주요 차이점은Lookup 변경 불가능합니다. Add()메서드와 퍼블릭 생성자 가 없습니다 (존이 언급했듯이 예외없이 존재하지 않는 키를 쿼리하고 그룹화의 일부로 키를 가질 수 있음).

어느 것을 사용 하느냐에 따라 실제로 어떻게 사용 하느냐에 달려 있습니다. 지속적으로 수정되는 여러 값에 대한 키 맵을 유지 관리하는 경우Dictionary<Key, List<Value>> 는 변경 가능하므로 더 좋습니다.

그러나 일련의 데이터가 있고 키로 구성된 데이터에 대한 읽기 전용보기 만 원하는 경우 조회를 구성하는 것이 매우 쉽고 읽기 전용 스냅 샷을 제공합니다.


11

ILookup<K,V>a와 a 의 주요 차이점은 Dictionary<K, List<V>>사전을 변경할 수 있다는 것입니다. 키를 추가하거나 제거 할 수 있으며 조회 한 목록에서 항목을 추가하거나 제거 할 수도 있습니다. 은 ILookup이다 불변 및 생성 후 수정할 수 없습니다.

두 메커니즘의 기본 구현은 동일하거나 유사하므로 검색 속도와 메모리 풋 프린트가 거의 동일합니다.


1
@JohnBustos 성능 측면에서 그렇습니다. 순전히 논리적입니다. 다른 사람이 당신의 아래에서 그것을 수정하는 것에 대해 걱정하지 않고 구조에 대한 참조를 전달할 수 있습니다. 변경할 수 없다면 변경할 수 없다는 사실을 가정 할 수 있습니다.
Servy

감사합니다, Servy, 그것은 당신이 많은 변수를 자주 지나갈 때 아주 좋은 점입니다. ByRef-적어도 당신이 확신 할 수있는 것은 수정 될 수 없습니다. 감사!
존 Bustos

2
@JohnBustos 메소드 매개 변수를 전달하는 기본 메소드는 값에 의한 것이므로 명시 적으로 byref를 추가해야하며 이는 거의 수행되지 않는 것입니다. 이러한 데이터 구조는 클래스이므로 참조 유형을 참조하므로 값을 전달하는 것이 참조의 값이므로 다른 메소드로 전달하면 호출자에게 눈에 띄는 변경이 발생할 수 있습니다.
Servy

고마워, Servy, 내가하고있는 일에 관해서 완전히 새로운 웜 캔을 열어 주지만, 나는 당신이 말하는 것을 이해합니다. 감사!!
John Bustos

덮개 아래에서 Lookup이 키에 해시 버킷을 사용하는지 알고 있습니까?
paparazzo

10

아직 언급되지 않은 또 다른 차이점은 Lookup () 이 null 키를 지원 한다는 것입니다 .

Lookup 클래스는 ILookup 인터페이스를 구현합니다. 조회는 여러 값이 동일한 키에 맵핑 될 수 있고 널 키가 지원된다는 점을 제외하면 사전과 매우 유사합니다.


4

예외가 옵션이 아닌 경우 조회로 이동하십시오.

a만큼 효율적인 구조를 얻으려고 Dictionary하지만 입력에 중복 키가 없는지 확실하지 않으면 Lookup더 안전합니다.

다른 답변에서 언급했듯이 null 키도 지원하며 임의의 데이터로 쿼리 할 때 항상 유효한 결과를 반환하므로 알 수없는 입력에 더 탄력적 인 것으로 보입니다 (예외보다 예외가 발생하기 쉽습니다).

그리고 System.Linq.Enumerable.ToDictionary함수와 비교하면 특히 그렇습니다 .

// won't throw
new[] { 1, 1 }.ToLookup(x => x); 

// System.ArgumentException: An item with the same key has already been added.
new[] { 1, 1 }.ToDictionary(x => x);

대안은 foreach루프 내에서 자신의 중복 키 관리 코드를 작성하는 것 입니다.

성능 고려 사항, 사전 : 확실한 승자

목록이 필요하지 않고 많은 수의 항목을 관리하려는 경우 Dictionary(또는 사용자 정의 된 맞춤 구조) 더 효율적일 수 있습니다.

        Stopwatch stopwatch = new Stopwatch();
        var list = new List<string>();
        for (int i = 0; i < 5000000; ++i)
        {
            list.Add(i.ToString());
        }
        stopwatch.Start();
        var lookup = list.ToLookup(x => x);
        stopwatch.Stop();
        Console.WriteLine("Creation: " + stopwatch.Elapsed);

        // ... Same but for ToDictionary
        var lookup = list.ToDictionary(x => x);
        // ...

으로 Lookup는 (항목의 거대한 수의 3 배 느린 정도) 느린 사전보다, 각 키에 대한 항목의 목록을 유지해야한다

조회 속도 : 생성 : 00 : 00 : 01.5760444

사전 속도 : 제작 : 00 : 00 : 00.4418833

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.