어떤 데이터 구조가 가장 효율적인지, 언제 어디에서 어떤 데이터 구조를 사용 해야하는지 내 머리를 감싸려고합니다.
이제 구조를 충분히 이해하지 못했을 수도 있지만 어떻게 ILookup(of key, ...)
다른 Dictionary(of key, list(of ...))
가요?
또한 어디에서 사용하고 싶고 ILookup
프로그램 속도 / 메모리 / 데이터 액세스 등의 측면에서 더 효율적입니까?
답변
두 가지 중요한 차이점 :
Lookup
불변입니다. Yay 🙂 (적어도 구체적인Lookup
클래스는 불변이고ILookup
인터페이스는 변경 멤버를 제공하지 않습니다. 물론 다른 변경 가능한 구현 이 있을 수 있습니다.)- 조회에없는 키를 조회하면
KeyNotFoundException
. 대신 빈 시퀀스가 다시 나타납니다 . 따라서TryGetValue
AFAICR 은 없습니다 .
그것들은 효율성면에서 동등 할 것 Dictionary<TKey, GroupingImplementation<TValue>>
입니다. 예를 들어, 룩업은 배후에서 잘 사용할 수 있습니다 . 요구 사항에 따라 둘 중에서 선택하십시오. 개인적으로 조회는 일반적으로 Dictionary<TKey, List<TValue>>
위의 처음 두 지점으로 인해 보다 낫습니다 .
구현 세부 사항으로, 구체적인 구현은 IGrouping<,>
값 구현 IList<TValue>
에 사용됩니다 Count()
. ElementAt()
즉와 함께 사용하는 것이 효율적임을 의미합니다 .
답변
아무도 실제로 가장 큰 차이점을 언급하지 않았다는 점에 흥미가 있습니다 ( MSDN 에서 직접 가져옴 )
조회는 사전과 유사합니다. 차이점은 Dictionary는 키를 단일 값에 매핑하고 Lookup은 키를 값 모음에 매핑한다는 것입니다.
답변
a Dictionary<Key, List<Value>>
와 Lookup<Key, Value>
논리적으로 데이터를 유사한 방식으로 구성 할 수 있으며 둘 다 동일한 순서로 효율성을 갖습니다. 주요 차이점은Lookup
변경 불가능합니다. Add()
메서드와 퍼블릭 생성자 가 없습니다 (존이 언급했듯이 예외없이 존재하지 않는 키를 쿼리하고 그룹화의 일부로 키를 가질 수 있음).
어느 것을 사용 하느냐에 따라 실제로 어떻게 사용 하느냐에 달려 있습니다. 지속적으로 수정되는 여러 값에 대한 키 맵을 유지 관리하는 경우Dictionary<Key, List<Value>>
는 변경 가능하므로 더 좋습니다.
그러나 일련의 데이터가 있고 키로 구성된 데이터에 대한 읽기 전용보기 만 원하는 경우 조회를 구성하는 것이 매우 쉽고 읽기 전용 스냅 샷을 제공합니다.
답변
ILookup<K,V>
a와 a 의 주요 차이점은 Dictionary<K, List<V>>
사전을 변경할 수 있다는 것입니다. 키를 추가하거나 제거 할 수 있으며 조회 한 목록에서 항목을 추가하거나 제거 할 수도 있습니다. 은 ILookup
이다 불변 및 생성 후 수정할 수 없습니다.
두 메커니즘의 기본 구현은 동일하거나 유사하므로 검색 속도와 메모리 풋 프린트가 거의 동일합니다.
답변
아직 언급되지 않은 또 다른 차이점은 Lookup () 이 null 키를 지원 한다는 것입니다 .
Lookup 클래스는 ILookup 인터페이스를 구현합니다. 조회는 여러 값이 동일한 키에 맵핑 될 수 있고 널 키가 지원된다는 점을 제외하면 사전과 매우 유사합니다.
답변
예외가 옵션이 아닌 경우 조회로 이동하십시오.
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