사전 대 목록


30

그래서 나는 Dictionary<int, int>오늘 직장에서 만났다 . 아마 방금 List<int>대신 사용했을 것이기 때문에 이것은 나에게 이상하게 보였습니다 . 차이점이 있습니까? 하나의 구조가 다른 구조보다 선호되는 사용 사례가 있습니까?


1
주어진 둘 이상의 정수 사이에 관계가 필요합니까? 그런 다음지도 (이 언어로 사전)가 의미가 있습니다.
Rig

3
이름 사전은 저에게 분명합니다. 빠른 것을 찾아 보려면 사전을 사용하십시오.
ChaosPandion

2
@ChaosPandion하십시오 List<T>.NET 프레임 워크는 룩업 동작은 전형적으로 랜덤 액세스 배열이다 내에 빠른 A의 이상이 Dictionary<int,T>.
Doc Brown

2
@DocBrown-숫자 인덱스를 키로 사용하는 다소 이상한 경우에만. 다른 현명한을 사용하면 조회 속도가 빨라 Dictionary<TKey, TValue>집니다.
ChaosPandion

2
@ 카오스이 질문은 그 이상한 사건 에 관한 것 입니다.
MarkJ

답변:


32

Dictionary<int, int>색인이 위치 게재 위치 외에 특별한 의미가 있는 경우 a를 사용합니다 .

가장 먼저 떠오르는 예는 데이터베이스에 id 열과 int 열을 저장하는 것입니다. 예를 들어, [person-id]열과 열 이 있으면이를 열로 [personal-pin]가져올 수 있습니다 Dictionary<int, int>. 이 방법 pinDict[person-id]은 PIN을 제공하지만 색인은 의미가 있으며의 위치가 아닙니다 List<int>.

그러나 실제로 두 개의 관련 정수 목록이 있으면 적절한 데이터 구조가 될 수 있습니다.


내 person-id의 ​​범위가 0, ..., 999이고 개인 핀 값을 1000 명 모두의 메모리에로드해야하는 경우 일반적으로 List<int>사전이 아닌을 선택합니다 . 아래 답변을 참조하십시오.
Doc Brown

3
예. 그러나 사전은 드문 드문 일 수 있습니다
jk.

@ jk : 정확히 내가 답을 정교화하려고했습니다.
Doc Brown

7
개인 PIN? 약간 중복되는 소리.
Jack

흠, 지수가 "특별한 의미"를 가질 때, 실제 시나리오에서, 그것들은 연속적인 범위 [0, ..., n]을 형성하지 않을 가능성이 높으므로 (이것은 필수는 아니지만) 명백한 잘못이 아니라 부정확합니다. 그럼에도 불구하고 IMHO의 결정은이 "특별한 의미"에 근거해서는 안되며, "키가 대략 간격 [0, ..., n]을 구성합니까"에만 근거해야합니다. 공감 자의 수에 따라 대부분의 독자들이 그 점을 놓쳤다 고 생각합니다.
Doc Brown

28

의 생각 List배열로하고, DictionaryA와 해시 테이블 . 당신은 단지을 사용 Dictionary하면지도에 필요한 (또는 동료) 경우 반면에, 값으로 의미있는 키 List만을 맵핑 (또는 동료) 값으로 위치 (또는 인덱스).

예를 들어, 사람의 나이와 키 사이의 연관성을 저장하려고한다고 가정하십시오. a Dictionary<int, int>를 사용 하여 사람의 나이 ( int)를 키 ()에 매핑 할 수 있습니다 int.

Dictionary<int, int> personHeightMap = new Dictionary<int, int>();

personHeightMap.Add(21, 185);
personHeightMap.Add(31, 174);

int height = personHeightMap.ContainsKey(21) ? personHeightMap[21] : -1;

매우 유용한 예는 아니지만 요점은 List이러한 값을 위치에 저장해야하기 때문에 우아하게 수행 할 수 없다는 것입니다.


7
+1은 주문List 과 거래 를 언급하며 , 여기서는 거래와 관련이 있습니다. 매번 특정 순서로 데이터를 가져와야하거나 서로 관련한 순서가 중요하다면 갈 길입니다. 정렬되지 않은 경향이 있으며 매핑 키-> 값 관계를 처리합니다. DictionaryListDictionaries
KChaloux

2
마지막으로, 찾고있는 것을 알면 해시 테이블은 약 O (1) 시간이며 배열은 가장 좋은 경우 (O (logN)이며 중복되지 않음) O (N)입니다. 최악의 경우.
JensG

1
+1. 어느 누구도 목록은 의미 론적으로 주문하고 dicts 절대적 인 의미 조회되어 있다는 점 해결해야 할 것 같다 근본적인 내 의견을,.
Benjamin Hodgson

15

의미 상 a Dictionary<int, T>List<T>매우 유사하며 둘 다 .NET 프레임 워크의 임의 액세스 컨테이너입니다. 사전을 대신하여 목록을 사용하려면 목록 의 빈 슬롯을 나타 내기 위해 유형에 특별한 값 T(예 null:)이 필요합니다. T와 같은 nullable 유형이 아닌 경우 대신 int사용할 수 int?있거나 양수 값만 저장하려는 경우 -1과 같은 특수 값을 사용하여 빈 슬롯을 나타낼 수도 있습니다.

선택할 값은 키 값의 범위에 따라 다릅니다. 키 Dictionary<int, T>가 정수 간격 내에 있고 키 사이에 많은 간격이없는 경우 (예 : [0, ... 100] 중 80 개 값) List<T>인덱스로 액세스하는 것이 빠르기 때문에 a 가 더 적합합니다. 이 경우 사전에 비해 메모리 및 시간 오버 헤드가 줄어 듭니다.

키 값이 int[0, ..., 1000000]과 같은 범위에서 100 개의 값인 경우 1000000 List<T>개의 T 값을 보유 할 메모리가 필요합니다. 여기서 사전은 T의 100 개 값 정도의 크기 순서로 메모리가 필요합니다. int의 100 값 (그리고 약간의 오버 헤드, 실제로는 100 개의 키와 값을 저장하는 데 약 2 배의 메모리가 필요합니다). 따라서 후자의 경우 사전이 더 적합합니다.


6
이것은 imho의 중요한 차이점입니다. Dictionary <int, int>는 드문 드문 일 수 있습니다
jk.

이 경우 List <KeyValuePair <int, int >>를 사용할 수 없습니까? 선형 탐색에 어떤 것이 더 좋을까요?
Deepak Mishra

@DeepakMishra : 여기서 가장 큰 차이점은와 함께 List<KeyValuePair<int,T>>사용할 수있는 O (1) 조회 작업이 없다는 것입니다. 둘째,의 요소는 List<KeyValuePair<int,T>>키 값과 관계없이 특정 순서를 가질 수 있습니다. 후자가 필요하지만 후자가 필요 List<KeyValuePair<int,T>>하거나 List<Tuple<int,T>>더 나은 선택 일 수 있습니다. 둘 다 필요한 경우도 있습니다 OrderedDictionary.
Doc Brown

@DocBrown 선형 탐색 (예 : foreach) 및 삽입 작업에 더 적합한 방법은 무엇입니까? 직접 조회가 필요하지 않습니까?
Deepak Mishra

@DeepakMishra : 소프트웨어 개발에서 "일반적으로 더 나은"것과 같은 것은 없습니다. 여기서 더 좋다는 것은 더 빠르고, 더 읽기 쉽고, 입력 할 코드가 적고, 향후 요구 사항에 따라 더 쉽게 확장 될 수 있음을 의미 할 수 있습니다. 그러나 일반적으로 이것을 지나치게 생각하지 말고, 문제를 올바르게 해결하고 눈에 가장 간단한 것을 구현하고 , 목적에 맞는 속도인지 확인 하고, 단점을 관찰 할 때 더 많은 생각 만 투자 하십시오 .
Doc Brown

6

누구나 동등하게 생각할 수 있습니까?

사전은 드문 드문하고 임의의 삽입을 허용하지만 순차 통과는 문제가되고 목록은 드문 드문하지 않으며 비 순차 삽입은 비싸며 본질적으로 순차 순회를 제공합니다.

하나가 다른 것보다 극적으로 우수하지 않은 상황은 거의 없습니다.


2

따로 : 다른 프로그래밍 언어는 이러한 유형의 데이터 구조를 사전이 아닌 맵으로 참조합니다.

데이터를 의미있게 키 / 값 쌍으로 정의 할 수 있으면 키를 사용하여 값을 찾아야하는 경우 사전에서 훨씬 빠르게 액세스 할 수 있습니다.

예를 들어, 고객 목록이 있다고 가정하십시오. 각 고객은 이름과 주소, 고유 한 고객 번호와 같은 세부 사항을 포함합니다. 처리중인 주문 목록도 있다고 가정하십시오. 각 주문에는 수행중인 내용에 대한 세부 정보가 포함되며 주문한 사람의 고객 번호를 포함해야합니다.

주문 배송 준비가 완료되면 배송 할 주소를 찾아야합니다. 고객이 일반 목록으로 저장된 경우 전체 고객 번호를 가진 고객을 찾으려면 전체 목록을 검색해야합니다. 대신 고객 번호를 키로 사용하여 고객을 사전에 저장할 수 있습니다. 사전을 사용하면 검색하지 않고도 한 번에 올바른 고객을 끌어낼 수 있습니다.


1

사전은 해싱을 사용하여 데이터를 검색합니다. 사전은 먼저 키의 해시 값을 계산했으며이 해시 값은 대상 데이터 버킷으로 이어집니다. 그런 다음 버킷의 각 요소가 동일한 지 확인해야합니다. 그러나 실제로 첫 번째 단계에서 검색 할 항목이 없기 때문에 첫 번째 항목 검색의 사전보다 목록이 더 빠릅니다. 그러나 두 번째 단계에서 목록은 첫 번째 항목과 두 번째 항목을 살펴 봐야합니다. 따라서 각 단계마다 조회 시간이 점점 더 걸립니다. 목록이 클수록 시간이 오래 걸립니다.

자세한 내용은 .... 사전사전 예제를 참조하십시오.


-1

문제의 코드가 두 세트의 상관 된 값을 저장하는 경우 Dictionary 클래스는 키를 사용하여 값을 찾는 색인 방식을 제공합니다. 이 값의 한 세트이지만, 그 세트가 무작위로 액세스 할 필요가있는 경우 (아마도 세트의 키의 존재를 확인하기 위해), 그리고 값이 고유하는 HashSet의 사용에 최적의 설정 클래스가 될 수 있습니다.


-3

이것들은 기초를 덮는 것처럼 보이는 훌륭한 답변입니다.

내가 제공 할 또 다른 고려 사항은 사전 (C #)이 코딩 관점에서 더 복잡하다는 것입니다. 동일한 코드베이스에 목록과 사전을 모두 사용하면 두 방법 모두 객체 데이터 검색 및 마샬링과 같은 기본 작업을 수행하는 방법에 미묘한 차이가 있으므로 코드를 유지하기가 더 어려워집니다. 내 관점은 정당한 이유로 사전이 필요하지 않으면 목록을 사용한다는 것입니다.


8
동의하지 않습니다. 사전 /지도는 모든 소프트웨어 엔지니어에게 친숙한 기본 데이터 구조입니다. 어느 쪽이든 : 데이터 구조를 사용하는 정당한 이유가 필요합니다. 목록 포함.
Steven Evers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.