C#에서 List와 Dictionary
오늘은 보다 간단한 주제를 가져와 보았다. 리스트(List)와 딕셔너리(Dictionary)는 C를 다루어본 사람이라면 모를 수 없는 개념일 것이다. C#에서는 이 두 가지의 자료구조가 제네릭 클래스이기 때문에, 게임오브젝트나 다른 객체 클래스를 포함한 어떠한 자료형이나 객체이든 사용할 수 있다. 리스트는 아래 코드와 같이 초기화할 수 있다.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
numbers.RemoveAll(x => x > 3); // 3보다 큰 모든 숫자 제거
numbers.Clear(); // 리스트의 모든 요소 제거
리스트란 주로 자료구조에서 연결 리스트와 같이 자주 등장하는 용어로, C#에서 동적 배열을 제공하며 일반적인 목록을 구현한다. 리스트는 요소를 추가, 제거 및 접근하는데 매우 간단히 사용된다. 아래는 리스트 클래스에서 자주 사용하는 메소드들이다.
위의 내용들을 종합해, 아래와 같이 간단한 리스트 스크립트를 생성할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class GenericList : MonoBehaviour
{
// 문자열용 리스트 생성
List<string> list = new List<string>();
// Start is called before the first frame update
void Start()
{
// 데이타 추가
list.Add("홍길동");
list.Add("김영희");
list.Add("박찬호");
list.Add("고영표");
for (int i=0; i<list.Count; i++) {
Debug.Log($"{i}번째 문자열 데이터 : {list[i]}");
}
Debug.Log("데이터 추가, 삽입 처리---------------------------------------");
// * 배열과의 핵심 차이점 : 중간 추가,삽입,삭제가 가능함
// 리스트의 맨 뒤에 문자열을 추가함
list.Add("로하스");
// 2번 인덱스 위치에 문자열을 추가함
list.Insert(2, "강백호");
for (int i = 0; i < list.Count; i++)
{
Debug.Log($"{i}번째 문자열 데이터 : {list[i]}");
}
Debug.Log("데이터 삭제 처리--------------------------------------");
string tempName = list[Random.Range(0,list.Count)];
Debug.Log($"{tempName} 이름이 삭제됨");
// 지정한 오브젝트의 참조값과 일치하는 요소를 삭제함
list.Remove(tempName);
Debug.Log($"{list[1]} 이름이 삭제됨");
list.RemoveAt(1);
for (int i = 0; i < list.Count; i++)
{
Debug.Log($"{i}번째 문자열 데이터 : {list[i]}");
}
}
}
이렇게 소개한 메소드로 간단한 리스트를 구현할 수 있다. 리스트는 배열과 같이 리스트 이름과 인덱스를 사용하여 접근할 수 있다는 것을 알아두어야 한다. 또한 C#에서는 LinkedList<T>라는 것이 존재하는데, List<T>로 구현하였는데 리스트를 조회하는 경우보다는 삽입 / 삭제하는 경우가 더 빈번할 경우 사용하기에 매우 용이하다.
다음으로는 딕셔너리이다. 딕셔너리는 크게 Key와 Value를 사용하여 자료를 정리할 수 있다. 두 가지 값은 리스트와 마찬가지로 딕셔너리도 제네릭 클래스에 포함되기 때문에 모든 자료형과 객체를 사용할 수 있다. 딕셔너리를 구현하여 사용할 수 있는 메소드는 아래와 같다.
위의 딕셔너리 메소드를 활용하여, 아래와 같이 딕셔너리 스크립트를 작성할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenericDictionary : MonoBehaviour
{
// 플레이점 점수 딕셔너리 생성
Dictionary<string, int> playerScoreMap = new Dictionary<string, int>();
// Start is called before the first frame update
void Start()
{
// 딕셔너리에 데이터 추가
playerScoreMap.Add("플레이어1", Random.Range(0, 1001));
playerScoreMap.Add("플레이어2", Random.Range(0, 1001));
playerScoreMap.Add("플레이어3", Random.Range(0, 1001));
playerScoreMap.Add("플레이어4", Random.Range(0, 1001));
Debug.Log("데이터 전체 출력---------------------------------------------");
// 딕셔너리를 순차적으로 접근하는 방법
foreach (KeyValuePair<string, int> playerScore in playerScoreMap)
{
Debug.Log($"키 : {playerScore.Key}, 값 : {playerScore.Value}");
}
Debug.Log("데이터 접근---------------------------------------------");
// 딕셔너리의 데이터 접근
Debug.Log($"플레이어3의 점수 : {playerScoreMap["플레이어3"]}");
// 잘못된 키의 값을 접근
//Debug.Log($"플레이어3의 점수 : {playerScoreMap["플레이어6"]}");
int score;
// 플레이어3 문자열 키를 가진 데이터블 안전하게 읽어옴
if (!playerScoreMap.TryGetValue("플레이어3", out score))
{
Debug.Log("플레이어 이름이 잘못되었음");
}
else
{
Debug.Log($"플레이어3의 점수 : {score}");
}
Debug.Log("데이터 유무 체크---------------------------------------------");
// 플레이어4 문자열 키가 존재하는지 파악
if (playerScoreMap.ContainsKey("플레이어4"))
{
Debug.Log($"플레이어4의 점수 : {playerScoreMap["플레이어4"]}");
}
Debug.Log("데이터 제거---------------------------------------------");
// 플레이어3 문자열 키를 가진 데이터를 삭제함
if (playerScoreMap.Remove("플레이어3"))
{
foreach (KeyValuePair<string, int> playerScore in playerScoreMap)
{
Debug.Log($"키 : {playerScore.Key}, 값 : {playerScore.Value}");
}
}
}
}
딕셔너리는 리스트와 다르게, 딕셔너리의 이름과 Key를 사용하면 Value에 접근할 수 있다. 예를 들면, 위와 같이 playerScoreMap["플레이어3"]이라고 작성하면 "플레이어3"을 Key로 가지고 있는 Value에 접근하여 read할 수 있는 것이다. 또한 위 스크립트를 보면 응용된 생소한 메소드들이 몇 가지 보인다. 아래에서 설명하겠다.
1. playerScoreMap.TryGetValue("플레이어3", out score) : 현재 구현한 playerScoreMap 딕셔너리는, Key = string, Value = int로 설정하였기 때문에 out score로 설정하였는데, 의미는 플레이어3이라는 Key를 가지고 있는 Value가 있다면 그 값을 score에 out을 적용하여 저장한 후 true를 반환한다. 하지만 해당하는 Value가 없다면 저장하지 않고 false를 반환한다.
2. ContainsKey("플레이어4") : 플레이어4라는 키를 가진 Value가 있는지 확인하여 Bool값으로 반환한다.
이와 같이, 리스트와 딕셔너리의 여러 요소들을 객체로 적용하여 게임 개발에 매우 유용하게 데이터를 저장하고 사용할 수 있다.