Hello ,
I had to write a custom BP node for a project I am working on. I thought I would share it with the community. Since you already have a good package of BP nodes, perhaps you could integrate into yours.
Node: ExplodeString
Description: Splits a string based on given delimiter. Unlike the ParseIntoArray() function, the delimiter can be a multi-character string (eg ‘::’). There is also aan optional automatic trimming that will cleanup the returned substrings.
I am attaching the source here and if anyone is interested, have fun :). Please note that currently it is implemented as a BlueprintFunctionLibrary, you might want to change that to suit your needs.
UStringUtils.h
#pragma once
#include "StringUtils.generated.h"
/**
*
*/
UCLASS()
class UStringUtils : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
/**
* Split a string into an array of substrings based on the given delimitter.
* Unlike ParseIntoArray() function which expects single character delimitters, function can accept a delimitter that is also a string.
*
* @param InputString - The string that is to be exploded.
* @param Separator - The delimitter that is used for splitting (multi character strings are allowed)
* @param limit - If greater than zero, returns only the first x strings. Otherwsie returns the substrings
* @param bTrimElelements - If True, then each subsctring is processed and any leading or trailing whitespcaes are trimmed.
*/
UFUNCTION(BlueprintPure, meta = (FriendlyName = "Explode string", Keywords = "split explode string"), Category = String)
static TArray<FString> ExplodeString(FString InputString, FString Separator = ",", int32 limit = 0, bool bTrimElements = false);
};
UStringUtils.cpp
#include "YourGame.h" //<- Change to match your-own header file
#include "StringUtils.h"
UStringUtils::UStringUtils(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
}
TArray<FString> UStringUtils::ExplodeString(FString InputString, FString Separator, int32 limit, bool bTrimElements)
{
TArray<FString> OutputStrings;
if (InputString.Len() > 0 && Separator.Len() > 0) {
int32 StringIndex = 0;
int32 SeparatorIndex = 0;
FString Section = "";
FString Extra = "";
int32 PartialMatchStart = -1;
while (StringIndex < InputString.Len()) {
if (InputString[StringIndex] == Separator[SeparatorIndex]) {
if (SeparatorIndex == 0) {
//A new partial match has started.
PartialMatchStart = StringIndex;
}
Extra.AppendChar(InputString[StringIndex]);
if (SeparatorIndex == (Separator.Len() - 1)) {
//We have matched the entire separator.
SeparatorIndex = 0;
PartialMatchStart = -1;
if (bTrimElements == true) {
OutputStrings.Add(FString(Section).Trim().TrimTrailing());
}
else {
OutputStrings.Add(FString(Section));
}
//if we have reached the limit, stop.
if (limit > 0 && OutputStrings.Num() >= limit) {
return OutputStrings;
}
Extra.Empty();
Section.Empty();
}
else {
++SeparatorIndex;
}
}
else {
//Not matched.
//We should revert back to PartialMatchStart+1 (if there was a partial match) and clear away extra.
if (PartialMatchStart >= 0) {
StringIndex = PartialMatchStart;
PartialMatchStart = -1;
Extra.Empty();
SeparatorIndex = 0;
}
Section.AppendChar(InputString[StringIndex]);
}
++StringIndex;
}
//If there is anything left in Section or Extra. They should be added as a new entry.
if (bTrimElements == true) {
OutputStrings.Add(FString(Section + Extra).Trim().TrimTrailing());
}
else {
OutputStrings.Add(FString(Section + Extra));
}
Section.Empty();
Extra.Empty();
}
return OutputStrings;
}
Usage and sample output: