¿Cómo ordenar por abecedario si el lenguaje considera que Z<Ñ?

Iniciado por Tachikomaia, 20 Octubre 2019, 17:54 PM

0 Miembros y 1 Visitante están viendo este tema.

Tachikomaia

Sólo estoy usando mayúsculas.

Si al programa le doy un texto C y quiero que el programa analice si el texto es mayor (es decir si en el abecedario está después) que "ZY", wait, creo que ya sé:
Z es considerado < Ñ.
Entonces hago:
Si "ZY" < C
  Si el Char0 de C es "Ñ"
    // C < "ZY"
  sino si el Char0 de C es "Z"
    Si el Char1 de C es "Ñ"
      // C < "ZY"
    sino si el Char1 de C es "Y"
      Si el Char2 de C no es Void/Null/undefined (debo ver cómo le llama mi lenguaje)
        // C == "ZY"
      sino
        // "ZY" < C


O:
Si "ZY" < C
  Si el Char0 de C es "Ñ"
    // C < "ZY"
  sino si el Char0 de C es "Z"
    Si el Char1 de C es "Ñ"
      // C < "ZY"
    sino si el Char1 de C es "Y"
      Si C == "ZY"
        // C == "ZY"
      sino
        // "ZY" < C


¿Correcto?

Ahora, si en vez de "ZY" fuese un texto variable, así como su cantidad de caracteres ¿cómo haría? Entiendo que debo usar un while pero el hecho de que pueda tener Ñ el texto también me complica un poco.

WHK

Hablando en temas de estándares la eñe tiene una posición binaria muy alejada del alfabeto normal que es a-z, de hecho en expresiones regulares decir a-z no incluye necesariamente letras con acentos o eñes, según latin iso y utf8 esos caracteres son considerados símbolos y no letras. Asi que, si tu software intenta ordenar estos caracteres de manera nativa te dará muchos problemas.

Entonces, ¿cómo considerar la eñe como alfabeto?: SQL como estandar, ya sea mysql, sql server o postgresql las eñes y acentos son considerados dentro del alfabeto como letras sin acento, esto quiere decir que realizar una búsqueda de "día" con acento tendrá el mismo resultado que "dia" sin acento. Para lograr esto SQL no utiliza el alfabeto normal estandarizado sino que lo incluye como parte de un tipo de conjunto de caracteres de tipo ascii personalizado.

Para llevar a la práctica esto deberás crear una lista de caracteres que tu software considerará como alfabeto y luego realizar el ordenamiento según el valor de índice de tu arreglo, que por ejemplo puede ser un const char array y luego hacer un for a cada uno e irlo inyectando a un segundo arreglo donde cada llave de índice es igual al índice de tu lista de caracteres y el valor es igual a la cantidad de caracteres existentes, luego simplemente escribes cada caracter según la cantidad dictada por ese segundo arreglo.

El problema de esto es que las letras con acento y eñes tienen un valor binario distinto según cada codificación de caracteres, en cambio el alfabeto normal siempre es el mismo valor (si, cuando crearon el sistema numérico en el alfabeto no pensaron en otro lenguaje que no fuera el inglés), por esto existen las funciones para codificar y decodificar textos en diferentes tipos de codificación de caracteres, justamente para transformar el valor binario de un caracter a otro valor equivalente.

En este caso lo que te recomiendo es que uses c++ y stdlib para procesar strings y no caracteres a nivel binario sino tendrás que reinventar la rueda intentando crear funciones y mapas de los valores de cada caracter y símbolo, luego usas algún diccionario o ordenador de alto nivel que use strings según la codificación actual de tu software y ya.

Recuerda que si vas a procesar y a guardar textos debes fijar una misma codificación de caracteres para todo, esto quiere decir, que si vas a procesar todo como utf8 tu base de datos o textos a guardar también deben estar en utf8 o si no tus acentos se verán con símbolos de euro en ves de letras. También debes considerar la codificación de caracteres de entrada según la consola de cada usuario, por ejemplo yo acostumbro a usar utf8 pero mucha gente de latinoamérica tiene sus consolas configuradas para latin iso y los valores binarios de las letras con acentos y eñes cambia.

Saludos.

@XSStringManolo

#2
Yo haría más o menos algo del estilo de:
Ejemplo C++
Código (cpp) [Seleccionar]
int restarINT = 'Ñ'-'N';
double restarDouble = static_cast<double>(restarINT) - 0.5;


if (caracter[i] == 'Ñ')
{
if( (static_cast<double>('Ñ') - restarDouble) > caracterComparar )
  {
  cout << "La Ñ va antes que la " << caracterComparar << endl;
  }

  else
  {
  cout << "La Ñ va despues que la " << caracterComparar << endl;
  }
}
Aquí simplemente cuando se encuentra la Ñ le otorgas el número 18.5 que es mayor que 18(N) y menor que 19(O). Por lo que podrías ordenar la Ñ entre esas 2 letras.



Ejemplo PHP:
Código (php) [Seleccionar]
<?php
   
function SMTaD($cipherText)
   {
   
$cipherTextTam strlen($cipherText);
   
$diccionario = array('a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','ñ','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C',
'D','E','F','G','H','I','J','K','L','M','N','Ñ','O','P','Q','R','S',
'T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0','.',
':','/',' ');
   
$diccionarioTam count($diccionario);
   
$cipherTextDec = [];
   
$y 0;
      for(
$i 0$i $cipherTextTam; ++$i)
      {
         for(
$x 0$x $diccionarioTam; ++$x)
         {
            if(
$cipherText[$i] == $diccionario[$x])
            {
            
$cipherTextDec[$y] = 1+$x;
            ++
$y;
            }
            else
            {
            
            }
         }
      }
   return 
$cipherTextDec;
   }
Aquí creo un diccionario y obtengo su orden en el mismo.
Si metes tu abecedario como te de la gana obtendrás un array contiendo el orden de cada letra.

Después puedes ordenar cada caracter mirando el array (recorriendo caracteres y array con el mismo iterador.)

O puedes convertir los números del array en el caracter correspondiente añadiéndolos a un nuevo array o string.


Ejemplo de esto último en PHP:
Código (php) [Seleccionar]
function SMDaT($cipherText)
   {
   $cipherTextTam = count($cipherText);
   $diccionario = array('a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','ñ','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C',
'D','E','F','G','H','I','J','K','L','M','N','Ñ','O','P','Q','R','S',
'T','U','V','W','X','Y','Z','1','2','3','4','5','6','7','8','9','0','.',
':','/','-','!','@','^','&','*','+','=','<','>','{','}','[',']','€','%','?','_','|',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','ñ','o','p','q','r','s',
't','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L',
'M','N','Ñ','O','P','Q','R','S','T','U','V','W','X','Y','Z'); $diccionarioTam = count($diccionario);
   $diccionario2 = array('1','2','3','4','5','6','7','8','9',
'10','11','12','13','14','15','16','17','18','19','20','21',
'22','23','24','25','26','27','28','29','30','31','32','33',
'34','35','36','37','38','39','40','41','42','43','44','45',
'46','47','48','49','50','51','52','53','54','55','56','57',
'58','59','60','61','62','63','64','65','66','67','68','69',
'70','71','72','73','74','75','76','77','78','79','80','81',
'82','83','84','85','86','87','88','89','90','91','92','93',
'94','95','96','97','98','99','100','101','102','103',
'104','105','106','107','108','109','110','111','112',
'113','114','115','116','117','118','119','120','121',
'122','123','124','125','126','127','128','129','130',
'131','132','133','134','135','136','137','138','139');
   $diccionario2Tam = count($diccionario2);
   $cipherTextText = [];
$z=0;
      for($i = 0; $i < $cipherTextTam; ++$i)
      {
         for($x =0; $x<$diccionarioTam; ++$x)
         {
            if($cipherText[$i] == $diccionario2[$x])
            {
            $cipherTextText[$z] = $diccionario[$x];
            ++$z;
            }
         }
      }
   return $cipherTextText;
   }


La logica de esto la puedes implementar en cualquier lenguaje.
Por si no entiendes bien lo que hacen las funciona de el PHP lo tengo muy comentado aquí:
https://github.com/StringManolo/SMDFPHC/blob/master/SMDFPHC.php