C#

[C#]Dictionary 특정 키가 존재하는지 확인하는 방법

DevStory 2022. 8. 18.

Dictionary 특정 키가 존재하는지 확인하는 방법

C#의 Dictionary 클래스는 <Key, Value> 형식의 컬렉션으로 키(Key)는 Dictionary 객체에서 중복되지 않은 고유한 값으로 설정되어야 합니다.

 

만약, 다음 예제처럼 Dicitionary의 키가 문자열 타입이고 중복되는 값을 키로 설정하는 경우 런타임 에러가 발생합니다.

class Program
{
  static void Main(string[] args)
  {
    Dictionary<string, int> dict = new Dictionary<string, int>();
    dict.Add("1000", 30);
    dict.Add("1000", 20);
  }
}

[에러 내용]

따라서, Dictionary 객체에 키-값을 추가하기 전에 키가 존재하는지 확인할 필요가 있습니다.

 

이번 포스팅은 Dictionary에 키가 존재하는지 확인할 수 있는 몇 가지 방법을 소개합니다.


방법 1. 반복문

가장 심플한 방법으로 반복문을 사용하여 Dictionary에 키가 존재하는지 확인할 수 있습니다.

 

다음 예제는 Dicitionary에 키가 존재하는지 확인하는 isHasKey() 메서드를 정의하였으며, 키가 존재하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

class Program
{
  public static bool isHasKey<K, V>(Dictionary<K, V> dict, K key)
  {
    foreach (KeyValuePair<K, V> kvp in dict)
    {
      if (kvp.Key.Equals(key))
      {
          return true;
      }
    }
    return false;
  }
  
  static void Main(string[] args)
  {
    Dictionary<string, int> dict = new Dictionary<string, int>();
    dict.Add("둘리", 10);
    dict.Add("또치", 20);
    dict.Add("마이콜", 20);

    Console.WriteLine("\"둘리\"는 Key로 등록되어 있는가? " + isHasKey(dict, "둘리"));
    Console.WriteLine("\"늑대\"는 Key로 등록되어 있는가? " + isHasKey(dict, "늑대"));
  }
}

[실행 결과]

"둘리"는 Key로 등록되어 있는가? True
"늑대"는 Key로 등록되어 있는가? False

방법 2. Dictionary 클래스의 ContainsKey 메서드

두 번째 방법으로 네임스페이스 System.Collections.Generic에 정의되어 있는 ContainsKey() 메서드를 사용합니다.

 

Dictionary 객체에서 ContainsKey() 메서드를 호출할 수 있으며, 매개변수로 키를 전달합니다.

 

키가 존재하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

 

반복문을 사용하는 방법보다 코드가 간결하다는 장점이 있습니다.

class Program
{
  static void Main(string[] args)
  {
    Dictionary<string, int> dict = new Dictionary<string, int>();
    dict.Add("둘리", 10);
    dict.Add("또치", 20);
    dict.Add("마이콜", 20);

    Console.WriteLine("\"둘리\"는 Key로 등록되어 있는가? " + dict.ContainsKey("둘리"));
    Console.WriteLine("\"늑대\"는 Key로 등록되어 있는가? " + dict.ContainsKey("늑대"));
  }
}

[실행 결과]

"둘리"는 Key로 등록되어 있는가? True
"늑대"는 Key로 등록되어 있는가? False

방법 3. LINQ의 Any 메서드

세 번째 방법으로 LINQ에서 제공하는 Any() 메서드를 사용합니다.

 

LINQ에서 제공하는 기능을 사용하기 위해 다음 네임스페이스를 소스 코드에 추가합니다.

using System.Linq;

Any() 메서드는 배열 또는 컬렉션과 같은 데이터 집합에서 특정 조건을 만족하는 데이터가 하나라도 있으면, true를 반환하고 그렇지 않으면 false를 반환합니다.

 

다음 예제는 Dicitionary에 키가 존재하는지 확인하는 isHasKey() 메서드를 정의하였으며, Any() 메서드를 사용하여 키가 존재하는지 검사합니다.

class Program
{
  public static bool isHasKey<K, V>(Dictionary<K, V> dict, K key)
  {
    return dict.Any(item => item.Key.Equals(key));
  }

  static void Main(string[] args)
  {
    Dictionary<string, int> dict = new Dictionary<string, int>();
    dict.Add("둘리", 10);
    dict.Add("또치", 20);
    dict.Add("마이콜", 20);

    Console.WriteLine("\"둘리\"는 Key로 등록되어 있는가? " + isHasKey(dict, "둘리"));
    Console.WriteLine("\"늑대\"는 Key로 등록되어 있는가? " + isHasKey(dict, "늑대"));
  }
}

[실행 결과]

"둘리"는 Key로 등록되어 있는가? True
"늑대"는 Key로 등록되어 있는가? False

LINQ에서 제공하는 Any() 메서드를 사용하는 방법은 아래 포스팅에서 확인할 수 있습니다.

 

[C#]LINQ 특정 조건을 만족하는지 체크하는 방법 - All, Any 메서드

Quantifiers 연산 Quantifiers 연산은 컬렉션과 같은 데이터 집합에서 모든 요소들이 특정 조건을 만족하는지 확인할 수 있는 방법들을 제공합니다. Quantifiers 연산에서 제공하는 메서드인 All(), Any(), Con

developer-talk.tistory.com


방법 4. 키가 사용자가 정의한 클래스 타입인 경우

Dictionary 객체의 키가 int, string, bool처럼 기본 타입이 아닌 사용자가 정의한 클래스 타입인 경우 키를 검사하는 방법이 생각보다 까다롭습니다.

 

다음 예제는 Dictionary의 키가 사용자가 정의한 클래스인 Person 타입입니다.

 

키의 타입이 기본 타입이 아닌 경우 값이 아닌 객체의 참조 값이 등록되므로 다음 예제처럼 동일한 프로퍼티 값을 가지는 객체를 키로 등록해도 런타임 에러가 발생하지 않습니다.

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
}

class Program
{
  public static bool isHasKey<K, V>(Dictionary<K, V> dict, K key)
  {
    return dict.Any(item => item.Key.Equals(key));
  }

  static void Main(string[] args)
  {
    Dictionary<Person, int> dict = new Dictionary<Person, int>();
    dict.Add(new Person() { Name = "둘리", Age = 10 }, 10);
    dict.Add(new Person() { Name = "둘리", Age = 10 }, 10);

    Console.WriteLine("new Person() { Name = \"둘리\", Age = 10 }은 Key로 등록되어 있는가? " + 
        dict.ContainsKey(new Person() { Name = "둘리", Age = 10 }));
  }
}

[실행 결과]

new Person() { Name = "둘리", Age = 10 }은 Key로 등록되어 있는가? False

참조 값이 아닌 프로퍼티 값을 비교하도록 Person 클래스에서 Equals() 메서드와 GetHashCode() 메서드를 재정의합니다.

public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }

  public override bool Equals(object x)
  {
    return this.Name == ((Person)x).Name && this.Age == ((Person)x).Age;
  }

  public override int GetHashCode()
  {
    return this.Name.GetHashCode() ^ this.Age.GetHashCode();
  }
}

class Program
{
  static void Main(string[] args)
  {
    Dictionary<Person, int> dict = new Dictionary<Person, int>();
    dict.Add(new Person() { Name = "둘리", Age = 10 }, 10);
    // 아래 주석 해제하면, 동일한 키가 존재하므로 런타임 에러 발생합니다.
    // dict.Add(new Person() { Name = "둘리", Age = 10 }, 10);

    Console.WriteLine("new Person() { Name = \"둘리\", Age = 10 }은 Key로 등록되어 있는가? " + 
        dict.ContainsKey(new Person() { Name = "둘리", Age = 10 }));
  }
}

[실행 결과]

new Person() { Name = "둘리", Age = 10 }은 Key로 등록되어 있는가? True

참조 값이 아닌 Person 클래스의 Name, Age 프로퍼티 값을 비교하도록 Equals() 메서드와 GetHashCode() 메서드를 재정의했습니다.

 

이제, 동일한 프로퍼티 값을 가지는 객체를 등록할 수 없으며, 실행 결과에서 키가 존재하는 것을 확인할 수 있습니다.

반응형

댓글