Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   [GH Freebrary] (https://www.clubdelphi.com/foros/forumdisplay.php?f=54)
-   -   Función ghEquals (https://www.clubdelphi.com/foros/showthread.php?t=83433)

Al González 17-06-2013 21:14:27

Función ghEquals
 
Determina si dos valores son equivalentes o no.

Unidad

GHFRTL

Declaración
Código Delphi [-]
  { Equals? }
  Function ghEquals (Const Value1, Value2 :String;
    Const CompareType :TghStrCompare = ghscLocaleAnyCase) :Boolean;
    Overload;

  { Equals? }
  Function ghEquals (Const Value1 :String; Const StartIndex :Integer;
    Const Value2 :String;
    Const CompareType :TghStrCompare = ghscLocaleAnyCase) :Boolean;
    Overload;
    
  { Equals? }
  Function ghEquals (Const Value1, Value2 :Variant) :Boolean; Overload;

  { Equals? }
  Function ghEquals (Const Value1, Value2 :TGUID) :Boolean; Overload;
Descripción

La función ghEquals permite comprobar si dos valores son iguales o equivalentes, en situaciones donde el operador relacional de igualdad (signo =) no resulta efectivo.

La primera sobrecarga de la función compara dos cadenas de caracteres dadas, bajo el criterio indicado por un tercer parámetro, CompareType, según el cual debe o no debe distinguir entre letras mayúsculas y minúsculas o entre letras con y sin signos diacríticos (acentos). La segunda sobrecarga de la función trabaja de forma similar a la anterior, solo que compara la primera cadena dada a partir de cierta posición de carácter (parámetro StartIndex) contra la segunda cadena completa. La tercera sobrecarga sirve para comparar el resultado de dos expresiones Variant, y comprobar si son variantes de valores equivalentes y además del mismo tipo, es decir, variantes idénticos. La cuarta sobrecarga permite determinar si dos valores de tipo TGUID (identificador único global) son exactamente el mismo.

Si se cumple la comprobación de igualdad, ghEquals devuelve el valor de True; en caso contrario el resultado es False.

Parámetros

Value1 — Primer valor a comparar. Expresión de tipo String, Variant, compatible con Variant o TGUID.

Value2 — Segundo valor a comparar. Expresión de tipo String, Variant, compatible con Variant o TGUID.

CompareType — Tipo de comparación a realizar con las cadenas de caracteres dadas. Debe ser alguna de las constantes que define el tipo de dato TghStrCompare. Este parámetro puede omitirse, su valor predeterminado es ghscLocaleAnyCase.

StartIndex — Indica el índice de carácter desde el cual se tomará el valor de la cadena de caracteres Value1 para compararlo con la cadena Value2. Este parámetro es útil para descartar caracteres que se encuentren al comienzo de Value1, como puede ser algún prefijo.

Ejemplos

En el siguiente bloque de código, la condición del primer If no se cumple pero la del segundo sí. Las cadenas de caracteres 'Titanic' y 'titanic' no son exactamente iguales, pero sí equivalentes.
Código Delphi [-]
Var
  S :String;
Begin
  S := 'Titanic';

  If S = 'titanic' Then  // False
    ShowMessage ('');

  If ghEquals (S, 'titanic') Then  // True
    ShowMessage ('The strings are equivalent.');
En el siguiente bloque de código, las condiciones del primer y del tercer If no se cumplen pero las del segundo y cuarto sí. Las cadenas de caracteres 'México', 'Mexico' y 'MEXICO' no son exactamente iguales, y para la función nativa ANSISameText (que es insensible a mayúsculas y minúsculas) tampoco son equivalentes. En cambio tales valores String sí son equivalentes para la función ghEquals, cuando se usa la opción ghscSimple (ignorar acentos) o ghscSimpleAnyCase (ignorar acentos y no distinguir entre mayúsculas y minúsculas).
Código Delphi [-]
  S := 'México';

  If S = 'Mexico' Then  // False
    ShowMessage ('');

  If ghEquals (S, 'Mexico', ghscSimple) Then  // True
    ShowMessage ('The strings are equivalent.');

  If ANSISameText (S, 'MEXICO') Then  // False
    ShowMessage ('');

  If ghEquals (S, 'MEXICO', ghscSimpleAnyCase) Then  // True
    ShowMessage ('The strings are equivalent.');
En el siguiente bloque de código, la condición del primer If no se cumple pero la del segundo sí. La subcadena de caracteres 'ffffffff' y la cadena 'FFFFFFFF' no son exactamente iguales, pero sí equivalentes.
Código Delphi [-]
  S := '0xffffffff';

  If Copy (S, 3, MaxInt) = 'FFFFFFFF' Then  // False
    ShowMessage ('');

  If ghEquals (S, 3, 'FFFFFFFF') Then  // True
    ShowMessage ('The strings are equivalent.');
En el siguiente bloque de código, la condición del primer If se cumple pero la del segundo no. El operador = determina que los valores de las variables Variant V1 y V2 son equivalentes aunque no sean del mismo tipo: el primer variante es un valor de punto flotante (tipo varDouble), mientras que el segundo es una cadena de caracteres (tipo varString). Esta diferencia de tipos hace que la función ghEquals devuelva False.
Código Delphi [-]
Var
  V1, V2 :Variant;
Begin
  V1 := 3.141516;
  V2 := '3.141516';

  If V1 = V2 Then  // True
    ShowMessage ('The variants are equivalent (but not equal).');

  If ghEquals (V1, V2) Then  // False
    ShowMessage ('');
En seguida cambiamos el valor de V2, asignándole el mismo valor de punto flotante que tiene V1. Ahora ghEquals devuelve True, por ser V1 y V2 dos variantes idénticos.
Código Delphi [-]
  V2 := 3.141516;

  If ghEquals (V1, V2) Then  // True
    ShowMessage ('The variants are identical.');
En el siguiente bloque de código, la condición del If se cumple porque las constantes CLASS_DOMDocument60 y ghciMSXMLDoc60 tienen exactamente el mismo valor TGUID.
Código Delphi [-]
Const
  CLASS_DOMDocument60 :TGUID = '{88D96A05-F192-11D4-A65F-0040963251E5}';
Begin
  If ghEquals (CLASS_DOMDocument60, ghciMSXMLDoc60) Then  // True
    ShowMessage ('The GUIDs are equal.');

Al González 12-01-2014 11:30:56

Agregué la nueva sobrecarga para comparar GUIDs (ghEquals con valores TGUID). Ésta surge porque sólo las versiones más recientes del compilador admiten comparar dos valores TGUID con el signo "=". Quiero añadir una nota al respecto en la descripción del mensaje anterior, pero sería bueno saber cuál fue la primera versión de Delphi que lo permite (o la última que no lo permite). ¿Podrían ayudarme con esa averiguación? Es muy sencillo, sólo intenten compilar algo como lo siguiente en cualquier versión posterior a la 2007 y anterior a la XE2 (he comprobado que 2007 no lo permite y XE2 sí):
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
Var
  G1, G2 :TGUID;
begin
  If G1 = G2 Then
end;
O bien que pudieran proporcionarme un enlace oficial que mencione desde qué versión es posible la comparación.

¡Muchas gracias!

Al González 14-01-2014 22:25:31

Cita:

Empezado por Al González (Mensaje 471575)
¿Podrían ayudarme con esa averiguación? Es muy sencillo, sólo intenten compilar algo como lo siguiente en cualquier versión posterior a la 2007 y anterior a la XE2 [...]:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
Var
  G1, G2 :TGUID;
begin
  If G1 = G2 Then
end;

Muchas gracias de antemano. :)

Al González 06-02-2014 20:38:21

¿Todavía ningún usuario de Delphi 2009, 2010 o XE ha tenido cinco minutos libres para ayudarle a un servidor con esa pequeña duda? Si su religión les impide responder en los foros también pueden hacerlo en Twitter. ;)

ecfisa 06-02-2014 22:39:16

Hola Al.

Lamento mucho no disponer de esas versiones para realizar la prueba. Pero sé que un colega amigo está usando la versión XE, hoy voy a intentar contactarlo para que la realice.
Con mi viejo y querido Delphi 7 me arreglo con la función IsEqualGuid

Saludos :)

Al González 07-02-2014 01:55:43

Cita:

Empezado por ecfisa (Mensaje 472398)
Lamento mucho no disponer de esas versiones para realizar la prueba. Pero sé que un colega amigo está usando la versión XE, hoy voy a intentar contactarlo [...]

Gracias Daniel. Tú siempre poniendo el ejemplo a los que poseen la inmensa fortuna de poder acceder a muchas versiones de Delphi. :)

Cita:

Empezado por ecfisa (Mensaje 472398)
Con mi viejo y querido Delphi 7 me arreglo con la función IsEqualGuid

:) Sí, sobre esa función comentábamos algo el otro día:
Cita:

Empezado por Al González (Mensaje 471326)
Ahora pasemos a las funciones átomo, también agregadas a GHFRTL.pas:
Código Delphi [-]
  { Equals? }
  Function ghEquals (Const Value1, Value2 :TGUID) :Boolean; Overload;
  Var
    GUID1 :Array [0..3] Of Integer Absolute Value1;
    GUID2 :Array [0..3] Of Integer Absolute Value2;
  Begin
    Result := (GUID1 [0] = GUID2 [0]) And (GUID1 [1] = GUID2 [1]) And
      (GUID1 [2] = GUID2 [2]) And (GUID1 [3] = GUID2 [3]);
  End;
En Delphi 7 todavía no era posible comparar dos valores TGUID usando el operador "=", y por muchos años la recomendación fue usar la función IsEqualGUID importada de OLE32.dll. Pero me surgió la pregunta: ¿qué tan eficiente será hacer una simple comparación de 16 bytes con IsEqualGUID? Por otra parte, encontré que las versiones recientes de Delphi sí admiten la comparación de TGUIDs con el operador "=". Cuando eso ocurre, el compilador inserta una llamada al método interno TGUID.Equal:
Código Delphi [-]
class operator TGUID.Equal(const Left, Right: TGUID): Boolean;
var
  a, b: PIntegerArray;
begin
  a := PIntegerArray(@Left);
  b := PIntegerArray(@Right);
  Result := (a^[0] = b^[0]) and (a^[1] = b^[1]) and (a^[2] = b^[2]) and (a^[3] = b^[3]);
end;
El cual es de cuatro a cinco veces más rápido que IsEqualGUID. Así que buscando algo similar para Delphi 7 creé esa función ghEquals, y para mi sorpresa resultó ligeramente más eficiente que el método TGUID.Equal (en Delphi 7 genera un poco menos de código máquina y en XE2 conviene añadirle la directiva InLine).

Verificar desde cuándo puede compilarse un "If GUID1 = GUID2 Then" no tiene otro propósito que ampliar la documentación que hay al respecto. Resulta gratificante publicar o ayudar a publicar respuestas a preguntas sobre Delphi que probablemente otras personas se hacen también. A veces son "pequeñeces", como en este caso, pero ¿qué información relevante no se compone de ellas?

No hay prisa ecfisa; cuando tu amigo pueda. :)

ecfisa 07-02-2014 02:35:29

Hola Alberto.

Lo prometido es deuda, me confirmó que el código compila sin errores en Delphi XE.

Saludos :)

Al González 07-02-2014 06:27:53

Cita:

Empezado por ecfisa (Mensaje 472403)
[...] me confirmó que el código compila sin errores en Delphi XE.

Muchas gracias, colega. :)

Ya sólo falta probar con Delphi 2009 y 2010. Sospecho que ambas versiones lo admiten también, pero habrá que esperar a que alguien lo confirme.


La franja horaria es GMT +2. Ahora son las 11:24:37.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi