[언리얼 엔진] TMap

    언리얼 엔진 TMap

    • 언리얼 엔진(Unreal Engine)에서 TArray 다음으로 많이 사용되는 TMap일 것이다.
    • 키와 값을 짝으로 데이터를 저장하는 방식
    • 키로 값을 검색하여 값을 얻을수 있다.

    만들고 채우기

    • Add 함수에 Key와 Value를 입력하여 컨테이너에 데이터를 추가한다.
    • 중복된 키를 추가하면 기존의 같은 키에 있는 Value를 대체한다.
    • Key만 넣게 되면 Value는 Value타입의 기본 생성자로 생성된다.
    TMap<int32, FString> FruitMap;
    
    FruitMap.Add(5, TEXT("Banana"));
    FruitMap.Add(2, TEXT("Grapefruit"));
    FruitMap.Add(7, TEXT("Pineapple"));
    // FruitMap == [
    //  { Key: 5, Value: "Banana"     },
    //  { Key: 2, Value: "Grapefruit" },
    //  { Key: 7, Value: "Pineapple"  }
    // ]
    
    FruitMap.Add(2, TEXT("Pear"));
    // FruitMap == [
    //  { Key: 5, Value: "Banana"    },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" }
    // ]
    
    FruitMap.Add(4);
    // FruitMap == [
    //  { Key: 5, Value: "Banana"    },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: ""          }
    // ]
    • TArray 처럼 Emplace 함수로 임시생성을 피할 수 있다.
    • Append 함수로 다른 TMap의 모든 엘리먼트를 삽입하여 병합할 수 있다.
    • Append 함수 사용시 키가 중복되는 값이 있으면 추가되는 값으로 대체된다.
    FruitMap.Emplace(3, TEXT("Orange"));
    // FruitMap == [
    //  { Key: 5, Value: "Banana"    },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: ""          },
    //  { Key: 3, Value: "Orange"    }
    // ]
    
    TMap<int32, FString> FruitMap2;
    FruitMap2.Emplace(4, TEXT("Kiwi"));
    FruitMap2.Emplace(9, TEXT("Melon"));
    FruitMap2.Emplace(5, TEXT("Mango"));
    FruitMap.Append(FruitMap2);
    // FruitMap == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     }
    // ]
    // 이제 FruitMap2 은 비워져 있다.

    반복처리

    • TArray와 유사하게 C++의 auto를 이욯나 for 기능 사용 가능
    • CreateIterator 를 통해 이터레이터로 반복 처리 가능
    for (auto& Elem : FruitMap)
    {
        FPlatformMisc::LocalPrint(
            *FString::Printf(
                TEXT("(%d, \"%s\")\n"),
                Elem.Key,
                *Elem.Value
            )
        );
    }
    // Output:
    // (5, "Mango")
    // (2, "Pear")
    // (7, "Pineapple")
    // (4, "Kiwi")
    // (3, "Orange")
    // (9, "Melon")
    
    for (auto It = FruitMap.CreateConstIterator(); It; ++It)
    {
        FPlatformMisc::LocalPrint(
            *FString::Printf(
                TEXT("(%d, \"%s\")\n"),
                It.Key(),   // same as It->Key
                *It.Value() // same as *It->Value
            )
        );
    }

    쿼리

    • Num 함수를 통해 엘리먼트의 갯수를 알 수 있다.
    • Contains 함수로 특정키가 있는지 검색할 수 있다.
    • [] 연산자로 해당값을 조회 할 수 있다.
    • Find 함수로 엘리먼트의 값의 포인터를 얻어올 수 있다.
    • FindorAdd 함수나 FindRef 함수는 결과의 유효성을 보장한다.
      (널이 리턴되지 않음)
    int32 Count = FruitMap.Num();   // Count == 6
    
    bool bHas7 = FruitMap.Contains(7);  // bHas7 == true
    bool bHas8 = FruitMap.Contains(8);  // bHas8 == false
    
    FString Val7 = FruitMap[7];         // Val7 == "Pineapple"
    FString Val8 = FruitMap[8];         // 어서트!
    
    FString* Ptr7 = FruitMap.Find(7);   // *Ptr7 == "Pineapple"
    FString* Ptr8 = FruitMap.Find(8);   //  Ptr8 == nullptr
    
    FString& Ref7 = FruitMap.FindOrAdd(7);
    // Ref7     == "Pineapple"
    // FruitMap == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     }
    // ]
    FString& Ref8 = FruitMap.FindOrAdd(8);
    // Ref8     == ""
    // FruitMap == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     },
    //  { Key: 8, Value: ""          }
    // ]
    
    FString Val7 = FruitMap.FindRef(7);
    FString Val6 = FruitMap.FindRef(6);
    // Val7     == "Pineapple"
    // Val6     == ""
    // FruitMap == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     },
    //  { Key: 8, Value: ""          }
    // ]
    • FindKey 함수는 값을 검사해서 키를 찾는다.
    • 선형 검사를 하기때문에 느리다.
      (그래도 필요하면 해야지)
      (그런데 필요할 경우가 생긴다면 TMap을 쓰면 안되지..)
    const int32* KeyMangoPtr   = FruitMap.FindKey(TEXT("Mango"));
    const int32* KeyKumquatPtr = FruitMap.FindKey(TEXT("Kumquat"));
    // *KeyMangoPtr   == 5
    //  KeyKumquatPtr == nullptr

    제거

    • Remove 함수는 인자에 키값을 넣으면 해당 키를 가진 엘리먼트가 제거된다.
    • Empty와 Reset 함수로 모든 엘리먼트를 삭제할 수 있다.
    • Empty는 남겨질 슬랙 양을 지정할 수 있고, Reset은 기존의 슬랙 양을 유지한다.
    FruitMap.Remove(8);
    // FruitMap == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     }
    // ]
    
    TMap<int32, FString> FruitMapCopy = FruitMap;
    // FruitMapCopy == [
    //  { Key: 5, Value: "Mango"     },
    //  { Key: 2, Value: "Pear"      },
    //  { Key: 7, Value: "Pineapple" },
    //  { Key: 4, Value: "Kiwi"      },
    //  { Key: 3, Value: "Orange"    },
    //  { Key: 9, Value: "Melon"     }
    // ]
    
    FruitMapCopy.Empty();       // 여기서 Reset() 을 호출해도 된다.
    // FruitMapCopy == []

    소팅

    • KeySort와 ValueSort 함수는 각각 키 / 값으로 지정한 술부를 통해 정렬을 할 수 있다.
    FruitMap.KeySort([](int32 A, int32 B) {
        return A > B; // sort keys in reverse
    });
    // FruitMap == [
    //  { Key: 9, Value: "Melon"  },
    //  { Key: 5, Value: "Mango"  },
    //  { Key: 4, Value: "Kiwi"   },
    //  { Key: 3, Value: "Orange" }
    // ]
    
    FruitMap.ValueSort([](const FString& A, const FString& B) {
        return A.Len() < B.Len(); // sort strings by length
    });
    // FruitMap == [
    //  { Key: 4, Value: "Kiwi"   },
    //  { Key: 5, Value: "Mango"  },
    //  { Key: 9, Value: "Melon"  },
    //  { Key: 3, Value: "Orange" }
    // ]

    연산자

    • TMap은 TArray와 같이 복사 생성자나 할당 연산자를 통해서 복사가 가능하다.
    • MoveTemp 함수로 이동 시멘틱 지원하여 이동 이후 기존 맵은 빈상태가 된다.
    TMap<int32, FString> NewMap = FruitMap;
    NewMap[5] = "Apple";
    NewMap.Remove(3);
    // FruitMap == [
    //  { Key: 4, Value: "Kiwi"   },
    //  { Key: 5, Value: "Mango"  },
    //  { Key: 9, Value: "Melon"  },
    //  { Key: 3, Value: "Orange" }
    // ]
    // NewMap == [
    //  { Key: 4, Value: "Kiwi"  },
    //  { Key: 5, Value: "Apple" },
    //  { Key: 9, Value: "Melon" }
    // ]
    
    FruitMap = MoveTemp(NewMap);
    // FruitMap == [
    //  { Key: 4, Value: "Kiwi"  },
    //  { Key: 5, Value: "Apple" },
    //  { Key: 9, Value: "Melon" }
    // ]
    // NewMap == []

    슬랙

    • Slack (여유분, 슬랙)은 할당된 메모리에 엘리먼트가 없는 것을 말한다.
    • Reserve 함수로 엘리먼트 없이 메모리만 할당 할 수 있다.
    FruitMap.Reserve(10);
    for (int32 i = 0; i < 10; ++i)
    {
        FruitMap.Add(i, FString::Printf(TEXT("Fruit%d"), i));
    }
    // FruitMap == [
    //  { Key: 9, Value: "Fruit9" },
    //  { Key: 8, Value: "Fruit8" },
    //  ...
    //  { Key: 1, Value: "Fruit1" },
    //  { Key: 0, Value: "Fruit0" }
    // ]
    • Compact 와 Shrink 함수로 슬랙을 제거 할 수 있다.
    • Shrink 함수는 컨테이너 중간의 슬랙부분은 제거하지 않고 끝의 모든 슬랙만 제거한다.
    • Compact 함수는 빈 슬랙을 컨테이너의 끝으로 모아준다.
    for (int32 i = 0; i < 10; i += 2)
    {
        FruitMap.Remove(i);
    }
    // FruitMap == [
    //  { Key: 9, Value: "Fruit9" },
    //  <invalid>,
    //  { Key: 7, Value: "Fruit7" },
    //  <invalid>,
    //  { Key: 5, Value: "Fruit5" },
    //  <invalid>,
    //  { Key: 3, Value: "Fruit3" },
    //  <invalid>,
    //  { Key: 1, Value: "Fruit1" },
    //  <invalid>
    // ]
    FruitMap.Shrink();
    // FruitMap == [
    //  { Key: 9, Value: "Fruit9" },
    //  <invalid>,
    //  { Key: 7, Value: "Fruit7" },
    //  <invalid>,
    //  { Key: 5, Value: "Fruit5" },
    //  <invalid>,
    //  { Key: 3, Value: "Fruit3" },
    //  <invalid>,
    //  { Key: 1, Value: "Fruit1" }
    // ]
    
    FruitMap.Compact();
    // FruitMap == [
    //  { Key: 9, Value: "Fruit9" },
    //  { Key: 7, Value: "Fruit7" },
    //  { Key: 5, Value: "Fruit5" },
    //  { Key: 3, Value: "Fruit3" },
    //  { Key: 1, Value: "Fruit1" },
    //  <invalid>,
    //  <invalid>,
    //  <invalid>,
    //  <invalid>
    // ]
    FruitMap.Shrink();
    // FruitMap == [
    //  { Key: 9, Value: "Fruit9" },
    //  { Key: 7, Value: "Fruit7" },
    //  { Key: 5, Value: "Fruit5" },
    //  { Key: 3, Value: "Fruit3" },
    //  { Key: 1, Value: "Fruit1" }
    // ]
    반응형

    댓글

    Designed by JB FACTORY