Necromancing.
come un servizio pubblico, questo è il modo in realtà CORRETTAMENTE invertire una stringa
(invertendo una stringa è NON pari ad invertire una sequenza di caratteri)
public static class Test
{
private static System.Collections.Generic.List<string> GraphemeClusters(string s)
{
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
System.Globalization.TextElementEnumerator enumerator = System.Globalization.StringInfo.GetTextElementEnumerator(s);
while (enumerator.MoveNext())
{
ls.Add((string)enumerator.Current);
}
return ls;
}
// this
private static string ReverseGraphemeClusters(string s)
{
if(string.IsNullOrEmpty(s) || s.Length == 1)
return s;
System.Collections.Generic.List<string> ls = GraphemeClusters(s);
ls.Reverse();
return string.Join("", ls.ToArray());
}
public static void TestMe()
{
string s = "Les Mise\u0301rables";
// s = "noël";
string r = ReverseGraphemeClusters(s);
// This would be wrong:
// char[] a = s.ToCharArray();
// System.Array.Reverse(a);
// string r = new string(a);
System.Console.WriteLine(r);
}
}
See: https://vimeo.com/7403673
A proposito, in Golang, il modo corretto è questo:
package main
import (
"unicode"
"regexp"
)
func main() {
str := "\u0308" + "a\u0308" + "o\u0308" + "u\u0308"
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme(str))
println("u\u0308" + "o\u0308" + "a\u0308" + "\u0308" == ReverseGrapheme2(str))
}
func ReverseGrapheme(str string) string {
buf := []rune("")
checked := false
index := 0
ret := ""
for _, c := range str {
if !unicode.Is(unicode.M, c) {
if len(buf) > 0 {
ret = string(buf) + ret
}
buf = buf[:0]
buf = append(buf, c)
if checked == false {
checked = true
}
} else if checked == false {
ret = string(append([]rune(""), c)) + ret
} else {
buf = append(buf, c)
}
index += 1
}
return string(buf) + ret
}
func ReverseGrapheme2(str string) string {
re := regexp.MustCompile("\\PM\\pM*|.")
slice := re.FindAllString(str, -1)
length := len(slice)
ret := ""
for i := 0; i < length; i += 1 {
ret += slice[length-1-i]
}
return ret
}
E il modo non corretto è questo (ToCharArray.Reverse):
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
Nota che è necessario conoscere la differenza tra
- un personaggio e un glifo
- un byte (8 bit) e una codepoint/runa (32 bit)
- un codepoint e un GraphemeCluster [32+ bit] (aka Grapheme/Glyph)
Reference:
Il carattere è un termine sovraccarico che può significare molte cose.
Un punto di codice è l'unità atomica di informazioni. Il testo è una sequenza di punti codice . Ogni punto di codice è un numero a cui viene assegnato il significato dallo standard Unicode .
Un grafema è una sequenza di uno o più punti di codice che vengono visualizzati come una singola unità grafica che un lettore riconosce come un singolo elemento del sistema di scrittura. Ad esempio, sia a che ä sono graphemes , ma possono essere costituiti da più punti di codice (ad esempio può essere due punti di codice, uno per il carattere di base a seguito da uno per la diaresi , ma c'è anche un'alternativa, eredità , punto codice singolo che rappresenta questo grafema). Alcuni punti di codice non fanno mai parte di alcun grafema (ad esempio il non-joiner a larghezza zero o gli override direzionali).
Un glifo è un'immagine, solitamente memorizzata in un carattere (che è una raccolta di glifi), utilizzata per rappresentare i grafemi o parti di essi. I caratteri possono comporre glifi multipli in una singola rappresentazione, ad esempio, se quanto sopra ä è un singolo punto di codice, un font può scegliere di renderlo come due glifi separati, spazialmente sovrapposti. Per OTF, le tabelle GSPOS e GPOS del font contengono informazioni di sostituzione e posizionamento per rendere questo lavoro . Un font può contenere più glifi alternativi per lo stesso grapheme .
Tenete a mente questo è più di un puzzle di un problema reale. Nella vita reale, puoi in genere solo invertire la stringa nel modo più comodo e andare avanti. Torna solo dopo che sei sicuro che sta causando problemi di prestazioni (di solito non lo farà) –
questo non è il mondo reale, il suo colloquio di lavoro. – IAdapter