String.split "" "" normally results in [""; ""], breaking up the visual character.
I want a function available that would instead return [""], not breaking up the visual character. These "visual characters" are referred to as TextElements in the .NET world, or EGCs (extended grapheme clusters) elsewhere, as far as I'm familiar.
Some details here: https://docs.microsoft.com/en-us/dotnet/api/system.globalization.textelementenumerator?view=net-6.0
Here's a bad solution I've made:
let ecgStringSplit'
(elements : string list)
(sep : string list)
: string list =
let startsWithSeparator (str : string list) =
sep = (str |> List.truncate sep.Length)
let mutable result = []
let mutable inProgress = []
let rec recursiveFn (elementsRemaining : string list) : unit =
if elementsRemaining = [] then
result <- result @ [ inProgress |> String.concat "" ]
elif startsWithSeparator elementsRemaining then
result <- result @ [ inProgress |> String.concat "" ]
inProgress <- []
recursiveFn (List.skip sep.Length elementsRemaining)
else
inProgress <- inProgress @ [ elementsRemaining.Head ]
recursiveFn elementsRemaining.Tail
recursiveFn elements
result
let toEgcList (s : string) : string list =
seq {
let tee = System.Globalization.StringInfo.GetTextElementEnumerator(s)
while tee.MoveNext() do
yield tee.GetTextElement()
} |> Seq.toList
let ecgStringSplit (str: string) (sep: string) =
ecgStringSplit' (toEgcList str) (toEgcList sep)
ecgStringSplit "Hello world 1" " " |> printfn "%A" // results in ["Hello"; "world"; "1"]
ecgStringSplit "" "" |> printfn "%A" // results in [""]
Beyond refactoring this to not use mutable values and such, I'm wondering if I'm missing a much simpler solution to this problem?
I'd happily take a C# solution that I can port to F#.
Edit: using something other than F# lists would certainly help perf.