-
[C#] Array, List, Dictionary 컬렉션 정리 겸 복습Programming/C# 2021. 1. 30. 12:41
(94) Array List Dictionary 유용한 함수들 - YouTube
고라니님의 Array, List, Dictionary를 통해 배운 내용을 정리해봤다.
Item 클래스
[System.Serializable] public class Item { public int code; public string name; public Item(int code, string name) { this.code = code; this.name = name; } public void Print() { Debug.Log($"code : {code}, name : {name}"); } }
Array
선언할 때는 Item을 new로 받은 다음, 대괄호 안에 아이템 객체를 생성함으로써 배열에 삽입을 할 수 있다.
[SerializeField] Item[] items = new Item[] { new Item(3, "carrot"), new Item(2, "banana"), new Item(1, "apple"), new Item(4, "apple") };
정렬
CASE 01
bool b; //오름차순 System.Array.Sort(items, (x, y) => x.code.CompareTo(y.code)); // 내림차순 System.Array.Sort(items, (x, y) => y.code.CompareTo(x.code));
CASE 02
System.Array.Sort(items, (x, y) => (x.code > y.code) ? 1 : -1); System.Array.Sort(items, (x, y) => (x.code < y.code) ? 1 : -1);
CASE01과 CASE02 는 동일한 역할을 한다.
x.CompareTo(y)는 만약 x가 y보다 더 클면 1을 반환하고 같으면 0을 반환하고 더 작을 때는 -1을 반환시켜주는 함수이다.
비슷한 함수로 string.Compare()가 있다.
ForEach
Array.ForEach(items, (e) => e.Print());
foreach (var e in items) { e.Print(); }
첫번째 꺼랑 두번째 꺼랑 같은 역할을 한다.
foreach는 배열에 있는 모든 요소들을 하나씩 꺼내오는 역할을 한다.
Exists
b = Array.Exists(items, x => x.code == 3); print("Array.Exists(items, x => x.code == 3) : " + b);
기존에 있는 요소가 존재하는지 여부를 반환함(존재하면 True, 존재하지 않는다면 False)
TrueForAll
b = Array.TrueForAll(items, e => e.code > 0); print("Array.TrueForAll(items, e => e.code > 0) : " + b); b = Array.TrueForAll(items, e => e.code > 1); print("Array.TrueForAll(items, e => e.code > 1) : " + b);
이름과 동일하게 배열 속의 모든 요소들이 지정한 조건에 모두 참이 되야 True를 리턴하고 하나라도 충족하지 못하면 False를 반환한다.
Find & FindIndex & FindLast & FindLastIndex & FindAll
Item item = Array.Find(items, e => e.name == "apple"); item?.Print(); int index = Array.FindIndex(items, e => e.name == "apple"); print("Array.FindIndex(items, e => e.name == apple : " + index); Item item02 = Array.FindLast(items, e => e.name == "apple"); item02.Print(); index = Array.FindLastIndex(items, e => e.name == "apple"); print("Array.FindLastIndex(items, e => e.name == apple : " + index); print("===================================================="); Item[] _items = Array.FindAll(items, e => e.name == "apple"); Array.ForEach(_items, e => e.Print()); print("====================================================");
Find는 해당 조건에 참이되는 요소가 있는지 앞에서부터 검사해서 있다면 해당 요소를 반환시켜 준다
FindIndex는 충족되는 조건을 앞에서부터 검사해서 있다면 해당 인덱스를 반환
FindLast는 조건이 참이되는 요소가 있는지 뒤에서부터 검사해서 참이면 해당되는 요소를 반환해준다.
FindLastIndex도 뒤에서부터 검사해서 참이되는 요소가 있다면 해당 인덱스를 반환해준다.
FindAll은 해당되는 조건의 모든 요소들을 찾아서 배열 형태로 리턴을 해준다.
얕은 복사와 깊은 복사
// 얕은 복사 (_items02 와 items 둘중 하나라도 수정하게 되면 둘다 같이 바뀜) Item[] _items02 = items; print("=================얕은 복사======================="); Array.FindLast(_items02, e => e.code == 4).code = 10; Array.ForEach(items, e => e.Print()); print("=================얕은 복사======================="); //깊은 복사 (둘중 하나라도 바뀌더라도 둘 다 변하지 않고 그대로 적용됨) Item[] _items03 = Array.ConvertAll(items, e => new Item(e.code, e.name)); print("=================깊은 복사======================="); Array.FindLast(_items03, e => e.code == 10).code = 4; Array.ForEach(items, e => e.Print()); print("=================깊은 복사=======================");
얖은 복사는 대입 형태(=)로 전달해주면 되지만 깊은 복사는 ConvertAll을 통해 전체를 모두 새로운 주소로 바꿔줘야 한다.
Reverse
// 오름차순 정렬 Array.Sort(items, (x, y) => x.code.CompareTo(y.code)); // 배열의 순서를 정반대로 Array.Reverse(items);
Reverse를 통해 배열을 반대로 뒤집어 줄 수 있다.
Resize
// 배열의 사이즈 변경 Array.Resize(ref items, 5); // 사이즈를 5로 늘림으로써 인덱스 4에 접근해서 넣을 수 있음 items[4] = new Item(5, "grape"); Array.ForEach(items, x => x?.Print());
배열의 사이즈 조정할 수 있다.
첫번째 매개변수에 ref키워드를 꼭 붙여줘야 한다.
List
List는 Resize를 제외하고 위에서 다뤘던 모든 함수들을 똑같히 쓸 수 있다.
Array랑 다르게 사이즈가 고정되지 않고 자유자제로 추가 및 삭제가 가능하다.
Dictionary
Dictionary 는 Key Value형태로 데이터를 저장해줄 수 있는 컨테이너이다.
Dictionary<string, Item> items_dic = new Dictionary<string, Item>() { {"banana", new Item(2,"banana_dic") }, {"apple", new Item(5, "apple_dic") } };
선언부는 Key, Value 형태에 맞춰서 선언을 해주면 된다.
Add, Remove
items_dic.Add("watermelon", new Item(3, "watermelon")); items_dic.Remove("watermelon"); foreach (var v in items_dic) { print(v.Key); v.Value.Print(); }
Add(key, value)를 통한 추가가 가능하고 Remove(key)를 통해 삭제가 가능하다.
ContainsKey, ContainsValue, TryGetValue
b = items_dic.ContainsKey("apple"); print("items_dic.ContainsKey(apple) : " + b); Item _item = new Item(2, "lemon_dic"); b = items_dic.ContainsValue(_item); print("items_dic.ContainsValue(_item) : " + b); items_dic.Add("lemon", _item); b = items_dic.ContainsValue(_item); print("items_dic.ContainsValue(_item) : " + b); if (items_dic.TryGetValue("apple", out Item apple)) { apple.Print(); }
ContainsKey로 해당 키가 존재하는지 여부를 알 수 있다.
ContainsValue는 해당 Value가 Dictionary에 존재하는지 알 수 있다.
TryGetValue는 해당 키가 존재하는지 검사하고 만약 존재하고 있다면 해당 Value를 리턴해준다.
+ ContainsKey등을 통해서 찾을 때 GC Alloc이 발생하는 경우도 있는데, 이때는 박싱때문에 발생하는 문제이기 때문에 IEqualityComparer을 통해 따로 만들어주면 GC Alloc을 줄일 수 있다고 한다.
전체코드
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; namespace List_Dictionary_Array { [System.Serializable] public class Item { public int code; public string name; public Item(int code, string name) { this.code = code; this.name = name; } public void Print() { Debug.Log($"code : {code}, name : {name}"); } } public class Test : MonoBehaviour { [SerializeField] Item[] items = new Item[] { new Item(3, "carrot"), new Item(2, "banana"), new Item(1, "apple"), new Item(4, "apple") }; [SerializeField] List<Item> items_List = new List<Item>() { new Item(3,"apple") }; Dictionary<string, Item> items_dic = new Dictionary<string, Item>() { {"banana", new Item(2,"banana_dic") }, {"apple", new Item(5, "apple_dic") } }; enum TEST { A, B, C, D, E } Dictionary<TEST, Item> test_dic = new Dictionary<TEST, Item>(new StateComparer()) { {TEST.A, new Item(2,"banana_dic") }, {TEST.B, new Item(5, "apple_dic") }, }; class StateComparer : IEqualityComparer<TEST> { public bool Equals(TEST x, TEST y) { return x == y; } public int GetHashCode(TEST obj) { return (int)obj; } } void Start() { bool b; //오름차순 System.Array.Sort(items, (x, y) => x.code.CompareTo(y.code)); // 내림차순 System.Array.Sort(items, (x, y) => y.code.CompareTo(x.code)); //System.Array.Sort(items, (x, y) => (x.code > y.code) ? 1 : -1); Array.ForEach(items, (e) => e.Print()); b = Array.Exists(items, x => x.code == 3); print("Array.Exists(items, x => x.code == 3) : " + b); b = Array.TrueForAll(items, e => e.code > 0); print("Array.TrueForAll(items, e => e.code > 0) : " + b); b = Array.TrueForAll(items, e => e.code > 1); print("Array.TrueForAll(items, e => e.code > 1) : " + b); b = Array.Exists(items, e => e.code == 3); print("Array.Exists(items, e => e.code == 3) : " + b); b = Array.Exists(items, e => e.code == 6); print("Array.Exists(items, e => e.code == 6) : " + b); Item item = Array.Find(items, e => e.name == "apple"); item?.Print(); int index = Array.FindIndex(items, e => e.name == "apple"); print("Array.FindIndex(items, e => e.name == apple : " + index); Item item02 = Array.FindLast(items, e => e.name == "apple"); item02.Print(); index = Array.FindLastIndex(items, e => e.name == "apple"); print("Array.FindLastIndex(items, e => e.name == apple : " + index); print("===================================================="); Item[] _items = Array.FindAll(items, e => e.name == "apple"); Array.ForEach(_items, e => e.Print()); print("===================================================="); // 얕은 복사 (_items02 와 items 둘중 하나라도 수정하게 되면 둘다 같이 바뀜) Item[] _items02 = items; print("=================얕은 복사======================="); Array.FindLast(_items02, e => e.code == 4).code = 10; Array.ForEach(items, e => e.Print()); print("=================얕은 복사======================="); //깊은 복사 (둘중 하나라도 바뀌더라도 둘 다 변하지 않고 그대로 적용됨) Item[] _items03 = Array.ConvertAll(items, e => new Item(e.code, e.name)); print("=================깊은 복사======================="); Array.FindLast(_items03, e => e.code == 10).code = 4; Array.ForEach(items, e => e.Print()); print("=================깊은 복사======================="); Array.Sort(items, (x, y) => x.code.CompareTo(y.code)); Array.Reverse(items); Array.Resize(ref items, 5); items[4] = new Item(5, "grape"); Array.ForEach(items, x => x?.Print()); items_dic.Add("watermelon", new Item(3, "watermelon")); items_dic.Remove("watermelon"); foreach (var v in items_dic) { print(v.Key); v.Value.Print(); } b = items_dic.ContainsKey("apple"); print("items_dic.ContainsKey(apple) : " + b); Item _item = new Item(2, "lemon_dic"); b = items_dic.ContainsValue(_item); print("items_dic.ContainsValue(_item) : " + b); items_dic.Add("lemon", _item); b = items_dic.ContainsValue(_item); print("items_dic.ContainsValue(_item) : " + b); if (items_dic.TryGetValue("apple", out Item apple)) { apple.Print(); } } private void Update() { var b = test_dic.ContainsKey(TEST.D); var i = test_dic[TEST.A]; } } }
'Programming > C#' 카테고리의 다른 글
[C#] Enum 변수를 추가 정의하여 사용하는 방법 (0) 2021.07.06 [C#] 확장 메소드(this) (0) 2020.10.11 C# 자료형 정리 (0) 2020.02.17