반응형
스크립트를 작성하다보면 아래와 같은 상황이 자주 연출됩니다.
private static void Function()
{
List<int> list = new List<int>();
list.Add(0);
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
var first = list[0];
var last = list[list.Count - 1];
}
코드에는 아무런 문제가 없지만, 가독성에 있어서 적합하지 않습니다. 또한 위의 코드처럼 특정 Collection뿐만이 아니라 Collection마다 First, Last를 가져오는 방식은 여러가지입니다.
private static void Function()
{
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "A");
dic.Add(0, "B");
dic.Add(4, "C");
dic.Add(3, "D");
dic.Add(2, "E");
var enumerator = dic.GetEnumerator();
KeyValuePair<int, string> first, last;
while (enumerator.MoveNext())
{
// ...?
}
}
Dictionary의 경우는 방법은 여러가지이지만 코드가 더욱 복잡해집니다. 물론 Dictionary 사용 용도에는 안 맞을 수 있지만, 코드를 사용하다보면 처음과 끝이 필요할 때가 더러 있습니다.
아래와 같이 모든 컬렉션에 처음과 마지막을 깔끔하게 가져오는 확장 함수를 만들어서 사용할 수 있습니다.
public static class CollectionUtils
{
/// <summary>
/// 컬렉션 첫번째 값 가져오기
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <returns></returns>
public static T GetFirst<T>(this ICollection<T> collection)
{
if (collection.Count > 0)
{
var enumerator = collection.GetEnumerator();
enumerator.MoveNext();
return enumerator.Current;
}
return default(T);
}
/// <summary>
/// 컬렉션 마지막 값 가져오기
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <returns></returns>
public static T GetLast<T>(this ICollection<T> collection)
{
if (collection.Count > 0)
{
var list = collection as List<T>;
if (list != null)
{
return list[list.Count - 1];
}
var array = collection as Array;
if (array != null)
{
return (T)array.GetValue(array.Length - 1);
}
T item = default(T);
var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
item = enumerator.Current;
}
return item;
}
return default(T);
}
/// <summary>
/// 이전 값 가져오기
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <param name="pivot"></param>
/// <returns></returns>
public static T GetPrevious<T>(this ICollection<T> collection, Predicate<T> match)
{
if (collection.Count > 0)
{
var enumerator = collection.GetEnumerator();
T previous = collection.GetLast();
while (enumerator.MoveNext())
{
if (match(enumerator.Current))
return previous;
previous = enumerator.Current;
}
}
return collection.GetFirst();
}
/// <summary>
/// 다음 값 가져오기
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <param name="pivot"></param>
/// <returns></returns>
public static T GetNext<T>(this ICollection<T> collection, Predicate<T> match)
{
if (collection.Count > 0)
{
var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
if (match(enumerator.Current))
{
if (!enumerator.MoveNext())
return collection.GetFirst();
else
return enumerator.Current;
}
}
}
return collection.GetFirst();
}
/// <summary>
/// 삭제
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection"></param>
/// <param name="match"></param>
/// <returns></returns>
public static bool Remove<T>(this ICollection<T> collection, Predicate<T> match)
{
if (collection.Count > 0)
{
T item = default;
var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
if (match(enumerator.Current))
{
item = enumerator.Current;
break;
}
}
if (item != default)
{
collection.Remove(item);
return true;
}
}
return false;
}
}
해당 코드는 아래처럼 사용할 수 있습니다.
private static void Function()
{
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "A");
dic.Add(0, "B");
dic.Add(4, "C");
dic.Add(3, "D");
dic.Add(2, "E");
//var enumerator = dic.GetEnumerator();
//KeyValuePair<int, string> first, last;
//while (enumerator.MoveNext())
//{
// // ...?
//}
var first = dic.GetFirst();
var last = dic.GetLast();
}
추가)
GetNext(), GetPrevious()는 해당되는 item에서 앞, 뒤 값을 가져옵니다. 개인적으로 리스트를 순환식으로 호출해야하는 작업이 있어서 작성하게된 함수입니다. 해당 함수는 반복해서 호출하면 순환식으로 쓸 수가 있습니다.
private static void Function()
{
List<int> list = new List<int>();
list.Add(0);
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
var prev = list.GetPrevious(item => item == 2); // result => 1
var next = list.GetNext(item => item == 2); // result => 3
}
반응형
'Utils' 카테고리의 다른 글
C#, 커스텀 밴치마크 라이브러리 (함수 테스트 도구) (2) | 2022.01.16 |
---|---|
유니티, 코루틴 최적화(Coroutine Yield Instruction) (0) | 2021.12.23 |
C#, Enum.GetMoveNext() 확장함수로 다음 값으로 넘기기 (2) | 2021.12.21 |
C#, Description 통한 Enum 관리하기 (0) | 2021.12.19 |
유니티, 런타임 중 특정 오브젝트 모두 찾기 (0) | 2021.12.19 |
댓글