[언리얼 엔진] 배열 TArray

    언리얼 엔진의 배열 TArray

    • TArray는 문자그대로 배열 컨테이너이며, 언리얼 엔진(Unreal Engine)에서 가장 자주 쓰이는 컨테이너 클래스이다.

    만들고 채우기

    • Init 함수로 배열을 같은 엘리먼트 사본으로 입력받은 갯수만큼 채운다
    //배열의 선언
    TArray<int32> IntArray;
    //Init 함수로 채우기
    IntArray.Init(10, 5);   //InitArray = [10,10,10,10,10]
    • Add와 Emplace 함수로 배열 끝에 항목을 추가할 수 있다.
    • Add는 객체를 복사하여 배열에 넣고 Emplace는 객체를 배열안에서 생성한다.
    • 간단한 유형(int, float 등)은 Add를 사용해도 무방하지만
    • 복잡한 구조체를 엘리먼트로 사용할때는 Emplace가 효율이 더 좋다.
    //배열 끝에 추가하기
    TArray<FString> StrArray;
    StrArray.Add(TEXT("Hello"));
    StrArray.Emplace(TEXT("World"));
    
    //StrArray = ["Hello", "World"]
    • Append 함수는 같은 유형의 다른 TArray 또는 일반 배열을 한꺼번에 추가가 가능하다.
    FString Arr[] = { TEXT("of"), TEXT("Tomorrow") };
    StrArray.Append(Arr, ARRAY_COUNT(Arr));
    // StrArray = ["Hello","World","of","Tomorrow"]
    • AddUnique 함수는 기존 컨테이너에 동일한 엘리먼트가 존재할 경우 추가하지 않아 중복된 데이터가 컨테이너에 포함되지 않도록 한다.
    • 엘리먼트에 operator== 연산자가 있어야한다.
    StrArray.AddUnique(TEXT("!"));
    // StrArray = ["Hello","World","of","Tomorrow"]
    
    StrArray.AddUnique(TEXT("!"));
    // 추가되지 않는다.
    // StrArray = ["Hello","World","of","Tomorrow"]
    • Insert 함수는 단일 값이나 배열 값을 입력한 인덱스 위치에 추가한다.
    StrArray.Insert(TEXT("Brave"), 1);
    // StrArray = ["Hello","Brave","World","of","Tomorrow"]
    • SetNum 함수는 배열의 크기를 설정할 수 있다.
    • 설정한 값이 현재 배열보다 큰 경우 기본 생성자의 값으로 추가
    • 배열보다 작은경우 뒤에서부터 항목을 제거
    StrArray.SetNum(8);
    // StrArray == ["Hello","Brave","World","of","Tomorrow","!","",""]
    
    StrArray.SetNum(6);
    // StrArray == ["Hello","Brave","World","of","Tomorrow","!"]

    반복처리

    • C++의 auto를 이용한 for 기능으로 반복처리 할 수 있다. (추천)
    • 인덱스 기반의 반복 처리또한 가능하다.
    • 반복자(iterator)를 통한 반복 처리도 가능하다.
    FString JoinedStr;
    for (auto& Str : StrArray)
    {
        JoinedStr += Str;
        JoinedStr += TEXT(" ");
    }
    
    for (int32 Index = 0; Index != StrArray.Num(); ++Index)
    {
        JoinedStr += StrArray[Index];
        JoinedStr += TEXT(" ");
    }
    
    for (auto It = StrArray.CreateConstIterator(); It; ++It)
    {
        JoinedStr += *It;
        JoinedStr += TEXT(" ");
    }
    
    // JoinedStr == "Hello Brave World of Tomorrow ! "

    정렬

    • TArray는 Sort함수로 간단한 정렬이 가능하다.
    • 엘리먼트의 < 연산자를 사용하여 배열을 정렬한다.
    • 2번째 인자에 조건을 직접 작성하여 정렬도 가능하다.
    • HeapSort함수로 힙정렬이 가능하다.
    • Sort와 HeapSort는 조건이 같은 값들의 순서를 기존과 동일하게 보장하지 않는 안정적이지 않은 정렬 함수
    • StableSort는 정렬이후 기존의 순서를 보장하지만 좀 더 느리다.
    StrArray.Sort();
    // StrArray == ["!","Brave","Hello","of","Tomorrow","World"]
    
    StrArray.Sort([](const FString& A, const FString& B) {
        return A.Len() < B.Len();
    });
    // StrArray == ["!","of","Hello","Brave","World","Tomorrow"]
    
    StrArray.HeapSort([](const FString& A, const FString& B) {
        return A.Len() < B.Len();
    });
    // StrArray == ["!","of","Hello","Brave","World","Tomorrow"]
    
    StrArray.StableSort([](const FString& A, const FString& B) {
        return A.Len() < B.Len();
    });
    // StrArray == ["!","of","Brave","Hello","World","Tomorrow"]

    쿼리

    • Num 함수는 배열의 갯수를 확인 할 수 있다.
    int32 Count = StrArray.Num();
    // Count == 6
    • GetData 함수는 배열의 포인터를 반환한다.
    FString* StrPtr = StrArray.GetData();
    
    // StrPtr[0] == "!"
    // StrPtr[1] == "of"
    // ...
    // StrPtr[5] == "Tomorrow"
    // StrPtr[6] - out of Index
    • [] 연산자로 인덱스 접근이 가능하다
    • [] 연산자는 레퍼런스를 반환하기 때문에 배열이 const가 아니라면 엘리먼트의 값을 변경할 수 있다.
    FString Elem1 = StrArray[1];
    // Elem1 == "of"
    
    StrArray[3] = StrArray[3].ToUpper();
    // StrArray == ["!","of","Brave","HELLO","World","Tomorrow"]
    • IsValidIndex 함수는 이름 그대로 인자값이 유효한 인덱스인지 검사한다
    bool bValidM1 = StrArray.IsValidIndex(-1);
    bool bValid0  = StrArray.IsValidIndex(0);
    bool bValid5  = StrArray.IsValidIndex(5);
    bool bValid6  = StrArray.IsValidIndex(6);
    // bValidM1 == false
    // bValid0  == true
    // bValid5  == true
    // bValid6  == false
    • Last 함수는 배열의 끝에서부터 역순으로 인덱스 접근을 한다
    • Top 함수는 Last와 같지만 인덱스접근이 불가능하다 (항상 끝 항목 접근)
    FString ElemEnd  = StrArray.Last();
    FString ElemEnd0 = StrArray.Last(0);
    FString ElemEnd1 = StrArray.Last(1);
    FString ElemTop  = StrArray.Top();
    // ElemEnd  == "Tomorrow"
    // ElemEnd0 == "Tomorrow"
    // ElemEnd1 == "World"
    // ElemTop  == "Tomorrow"
    • Contains는 배열에 특정 값을 검사할 수 있다.
    • ContainsByPredicate 함수는 술부(Predicate)를 작성하여 검사조건을 직접 정의할 수 있다.
    bool bHello   = StrArray.Contains(TEXT("Hello"));
    bool bGoodbye = StrArray.Contains(TEXT("Goodbye"));
    // bHello   == true
    // bGoodbye == false
    
    bool bLen5 = StrArray.ContainsByPredicate([](const FString& Str){
        return Str.Len() == 5;
    });
    bool bLen6 = StrArray.ContainsByPredicate([](const FString& Str){
        return Str.Len() == 6;
    });
    // bLen5 == true
    // bLen6 == false
    • Find함수로 특정 값에 대한 배열 인덱스값을 얻을 수 있다.
    • 값을 찾을 수 없다면 INDEX_NONE 값이 반환된다
    • 중복된 값이 있다면 첫번째로 발견한 인덱스값이 반환 된다
    • FindLast는 마지막으로 발견한 인덱스값이 반환된다.
    int32 Index;
    if (StrArray.Find(TEXT("Hello"), Index))
    {
        // Index == 3
    }
    
    int32 IndexLast;
    if (StrArray.FindLast(TEXT("Hello"), IndexLast))
    {
        // IndexLast == 3, because there aren't any duplicates
    }
    
    int32 Index2     = StrArray.Find(TEXT("Hello"));
    int32 IndexLast2 = StrArray.FindLast(TEXT("Hello"));
    int32 IndexNone  = StrArray.Find(TEXT("None"));
    // Index2     == 3
    // IndexLast2 == 3
    // IndexNone  == INDEX_NONE
    • IndexOfByKey 함수는 엘리먼트와 다른 타입의 비교가 가능하다.
    • 단 operator==(ElementType, OtherType)이 존재할 경우에 동작한다.
    • IndexOfByPredicate 함수는 설정한 술부로 조건을 정하여 해당 조건에 부합하는 엘리먼트의 인덱스값을 반환한다.
    int32 Index = StrArray.IndexOfByKey(TEXT("Hello"));
    // Index == 3
    
    int32 Index = StrArray.IndexOfByPredicate([](const FString& Str){
        return Str.Contains(TEXT("r"));
    });
    // Index == 2
    • FindByKey 함수는 IndexOfByKey 함수와 동일하게 검색하지만 포인터를 반환한다.
    • FindByPredicate 또한 IndexOfByPredicate처럼 검색하고 포인터를 반환한다.
    auto* OfPtr  = StrArray.FindByKey(TEXT("of")));
    auto* ThePtr = StrArray.FindByKey(TEXT("the")));
    // OfPtr  == &StStrArrayrArr[1]
    // ThePtr == nullptr
    
    auto* Len5Ptr = StrArray.FindByPredicate([](const FString& Str){
        return Str.Len() == 5;
    });
    auto* Len6Ptr = StrArray.FindByPredicate([](const FString& Str){
        return Str.Len() == 6;
    });
    // Len5Ptr == &StrArray[2]
    // Len6Ptr == nullptr
    • FilterByPredicate 함수는 배열에서 술부의 조건에 만족하는 항목들을 모아 새로 만든 배열을 반환한다.
    TArray<FString> Filter = StrArray.FilterByPredicate([](const FString& Str){
        return Str.Num() == 5;
    });
    // Filter == ["Brave","Hello","World"]

    제거

    • Remove 함수로 배열에서 엘리먼트를 지울수 있다.
    • == 연산자로 동일한 엘리먼트들을 삭제
    • RemoveSingle 함수는 처음으로 일치한 엘리먼트를 삭제한다.
    • RemoveAt은 인덱스로 위치를 지정하여 해당 엘리먼트를 삭제한다.
    • RemoveAt 사용시 인덱스가 유효한지 검사해야한다
    • RemoveAll 함수는 술부를 이용하여 조건에 만족하는 모든 항목을 삭제 한다.
    TArray<int32> ValArr;
    int32 Temp[] = { 10, 20, 30, 5, 10, 15, 20, 25, 30 };
    ValArr.Append(Temp, ARRAY_COUNT(Temp));
    // ValArr == [10,20,30,5,10,15,20,25,30]
    
    ValArr.Remove(20);
    // ValArr == [10,30,5,10,15,25,30]
    
    ValArr.RemoveSingle(30);
    // ValArr == [10,5,10,15,25,30]
    
    ValArr.RemoveAt(2); // 인덱스 2 엘리먼트를 제거
    // ValArr == [10,5,15,25,30]
    
    ValArr.RemoveAt(99); // 런타임 오류가 발생
    
    ValArr.RemoveAll([](int32 Val) {
        return Val % 3 == 0;
    });
    // ValArr == [10,5,25]
    • RemoveSwap, RemoveAtSwap, RemoveAllSwap 함수는 기존 함수에 비해 부하가 적다
    • 그러나 제거후 나머지 엘리먼트의 순서를 보장할 수 없다.
    • Empty함수는 모든 항목을 제거한다.
    TArray<int32> ValArr2;
    for (int32 i = 0; i != 10; ++i)
        ValArr2.Add(i % 5);
    // ValArr2 == [0,1,2,3,4,0,1,2,3,4]
    
    ValArr2.RemoveSwap(2);
    // ValArr2 == [0,1,4,3,4,0,1,3]
    
    ValArr2.RemoveAtSwap(1);
    // ValArr2 == [0,3,4,3,4,0,1]
    
    ValArr2.RemoveAllSwap([](int32 Val) {
        return Val % 3 == 0;
    });
    // ValArr2 == [1,4,4]
    
    ValArr2.Empty();
    // ValArr2 == []

    참고

    반응형

    댓글

    Designed by JB FACTORY