Necromancing.
Como servicio público, esta es la forma en que realmente CORRECTAMENTE invertir una cadena
(invirtiendo una cadena es NO igual a revertir una secuencia de caracteres)
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);
}
}
Ver: https://vimeo.com/7403673
Por cierto, en Golang, la forma correcta es la siguiente:
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
}
Y la manera incorrecta es la siguiente (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)
}
Tenga en cuenta que lo que necesita saber la diferencia entre
- un personaje y un glifo
- un byte (8 bits) y una punto de código/runa (32 bit)
- un punto de código y una GraphemeCluster [32+ bit] (también conocido como grafema/Glyph)
Reference:
El carácter es un término sobrecargado que puede significar muchas cosas.
Un punto de código es la unidad de información atómica. El texto es una secuencia de puntos de código. Cada punto de código es un número al que se le da significado por el estándar Unicode .
Un grafema es una secuencia de uno o más puntos de código que se muestran como una sola unidad gráfica que un lector reconoce como un único elemento del sistema de escritura. Por ejemplo, tanto a como ä son grafemas , pero pueden consistir en múltiples puntos de código (por ejemplo, ä pueden ser dos puntos de código, uno para el carácter base a seguido de uno para el dialogo , pero también existe una alternativa, legado , punto de código único que representa este grafema). Algunos puntos de código nunca forman parte de ningún grafema (por ejemplo, el no-empalmador de ancho cero o las anulaciones direccionales).
Un glifo es una imagen, generalmente almacenada en una fuente (que es una colección de glifos), que se usa para representar grafemas o partes de los mismos. Las fuentes pueden componer múltiples glifos en una sola representación, por ejemplo, si lo anterior ä es un único punto de código, una fuente puede elegir representarlo como dos glifos separados, espacialmente superpuestos. Para OTF, las tablas GPOS de la fuente GSUB y contienen información de sustitución y posicionamiento para hacer que funcione. Una fuente también puede contener múltiples glifos alternativos para el mismo grafema .
Tenga en cuenta que esto es más un rompecabezas que un problema real. En la vida real, generalmente puede invertir la cadena de la manera más conveniente y seguir adelante. Solo regrese después de estar seguro de que está causando problemas de rendimiento (generalmente no lo hará) –
esto no es real, su entrevista de trabajo. – IAdapter