1
0
mirror of https://github.com/php/doc-es.git synced 2026-03-23 23:12:09 +01:00
Files
archived-doc-es/language/operators/comparison.xml
2025-05-06 21:45:14 +02:00

557 lines
16 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 16934048f79c6e117cd16a23c09c1b2ea502e284 Maintainer: PhilDaiguille Status: ready -->
<!-- Reviewed: no -->
<sect1 xml:id="language.operators.comparison">
<title>Operadores de comparación</title>
<titleabbrev>Comparación</titleabbrev>
<simpara>
Los operadores de comparación, como su nombre indica,
permiten comparar dos valores. También se debe estar interesado por las
<link linkend="types.comparisons">tablas de comparaciones de tipos</link>,
ya que muestran ejemplos de muchos tipos de comparaciones.
</simpara>
<table>
<title>Operadores de comparación</title>
<tgroup cols="3">
<thead>
<row>
<entry>Ejemplo</entry>
<entry>Nombre</entry>
<entry>Resultado</entry>
</row>
</thead>
<tbody>
<row>
<entry>$a == $b</entry>
<entry>Igual</entry>
<entry>&true; si <varname>$a</varname> es igual a
<varname>$b</varname> después del transtipado.</entry>
</row>
<row>
<entry>$a === $b</entry>
<entry>Idéntico</entry>
<entry>
&true; si <varname>$a</varname> es igual a <varname>$b</varname> y
son del mismo tipo.
</entry>
</row>
<row>
<entry>$a != $b</entry>
<entry>Diferente</entry>
<entry>&true; si <varname>$a</varname> es diferente de
<varname>$b</varname> después del transtipado.</entry>
</row>
<row>
<entry>$a &lt;&gt; $b</entry>
<entry>Diferente</entry>
<entry>&true; si <varname>$a</varname> es diferente de
<varname>$b</varname> después del transtipado.</entry>
</row>
<row>
<entry>$a !== $b</entry>
<entry>Diferente</entry>
<entry>
&true; si <varname>$a</varname> es diferente de <varname>$b</varname>
o bien si no son del mismo tipo.
</entry>
</row>
<row>
<entry>$a &lt; $b</entry>
<entry>Menor que</entry>
<entry>&true; si <varname>$a</varname> es estrictamente menor que
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &gt; $b</entry>
<entry>Mayor</entry>
<entry>&true; si <varname>$a</varname> es estrictamente mayor que
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &lt;= $b</entry>
<entry>Menor o igual</entry>
<entry>&true; si <varname>$a</varname> es menor o igual a
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &gt;= $b</entry>
<entry>Mayor o igual</entry>
<entry>&true; si <varname>$a</varname> es mayor o igual a
<varname>$b</varname>.</entry>
</row>
<row>
<entry>$a &lt;=&gt; $b</entry>
<entry>Combinado</entry>
<entry>
Un &integer; menor, igual o mayor a cero cuando
<varname>$a</varname> es menor, igual, o mayor a
<varname>$b</varname> respectivamente.
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Si los dos operandos son
<link linkend="language.types.numeric-strings">strings numéricos</link>,
o si un operando es un número y el otro es un
<link linkend="language.types.numeric-strings">string numérico</link>,
entonces la comparación se efectuará numéricamente.
Estas reglas también se aplican a la instrucción
<link linkend="control-structures.switch">switch</link>.
La conversión de tipo no interviene cuando la comparación es
<literal>===</literal> o <literal>!==</literal>
ya que esto implica tanto una comparación de tipo como de valor.
</para>
<warning>
<para>
Antes de PHP 8.0.0, si un <type>string</type> es comparado a un número
o a un string numérico, entonces el <type>string</type> será convertido en un
número antes de efectuar la comparación. Esto puede llevar a resultados
sorprendentes como se puede ver en el siguiente ejemplo:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
switch ("a") {
case 0:
echo "0";
break;
case "a":
echo "a";
break;
}
?>
]]>
</programlisting>
&example.outputs.7;
<screen>
<![CDATA[
bool(true)
bool(true)
bool(true)
bool(true)
0
]]>
</screen>
&example.outputs.8;
<screen>
<![CDATA[
bool(false)
bool(true)
bool(true)
bool(true)
a
]]>
</screen>
</informalexample>
</para>
</warning>
<para>
<example>
<title>Operadores de comparación</title>
<programlisting role="php">
<![CDATA[
<?php
// Enteros
echo 1 <=> 1, ' '; // 0
echo 1 <=> 2, ' '; // -1
echo 2 <=> 1, ' '; // 1
// Números flotantes
echo 1.5 <=> 1.5, ' '; // 0
echo 1.5 <=> 2.5, ' '; // -1
echo 2.5 <=> 1.5, ' '; // 1
// Strings
echo "a" <=> "a", ' '; // 0
echo "a" <=> "b", ' '; // -1
echo "b" <=> "a", ' '; // 1
echo "a" <=> "aa", ' '; // -1
echo "zz" <=> "aa", ' '; // 1
// Arrays
echo [] <=> [], ' '; // 0
echo [1, 2, 3] <=> [1, 2, 3], ' '; // 0
echo [1, 2, 3] <=> [], ' '; // 1
echo [1, 2, 3] <=> [1, 2, 1], ' '; // 1
echo [1, 2, 3] <=> [1, 2, 4], ' '; // -1
// Objetos
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b, ' '; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b, ' '; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b, ' '; // 1
// No solo las valores son comparados; las claves deben coincidir
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b, ' '; // 1
?>
]]>
</programlisting>
</example>
</para>
<para>
Para los diferentes tipos, la comparación se realiza siguiendo
la tabla siguiente (en orden).
</para>
<table xml:id="language.operators.comparison.types">
<title>Comparación con múltiples tipos</title>
<tgroup cols="3">
<thead>
<row>
<entry>Tipo del operando 1</entry>
<entry>Tipo del operando 2</entry>
<entry>Resultado</entry>
</row>
</thead>
<tbody>
<row>
<entry><type>null</type> o <type>string</type></entry>
<entry><type>string</type></entry>
<entry>Convierte &null; en "", comparación numérica o léxica</entry>
</row>
<row>
<entry><type>bool</type> o <type>null</type></entry>
<entry>Cualquier cosa</entry>
<entry>Convierte en <type>bool</type>, &false; &lt; &true;</entry>
</row>
<row>
<entry><type>object</type></entry>
<entry><type>object</type></entry>
<entry>Las clases internas pueden definir su propio método de
comparación; diferentes clases son incomparables; entre objetos
de la misma clase ver <link
linkend="language.oop5.object-comparison">Comparación de objetos</link></entry>
</row>
<row>
<entry>
&string;, &resource;, &integer; o &float;
</entry>
<entry>
&string;, &resource;, &integer; o &float;
</entry>
<entry>
Transforma los strings y los recursos en números
</entry>
</row>
<row>
<entry><type>array</type></entry>
<entry><type>array</type></entry>
<entry>El array con menos miembros es menor, si la clave del operando 1 no es encontrada en el operando 2, entonces los arrays son incomparables, de lo contrario la comparación se realiza valor por valor (ver el siguiente ejemplo)
</entry>
</row>
<row>
<entry><type>object</type></entry>
<entry>Cualquier cosa</entry>
<entry>El <type>objeto</type> es siempre mayor</entry>
</row>
<row>
<entry><type>array</type></entry>
<entry>Cualquier cosa</entry>
<entry>El <type>array</type> es siempre mayor</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
<example>
<title>Comparación Booléen/null</title>
<programlisting role="php">
<![CDATA[
<?php
// Booléen y null siempre son comparados como booléans
var_dump(1 == TRUE); // TRUE - idéntico a (bool) 1 == TRUE
var_dump(0 == FALSE); // TRUE - idéntico a (bool) 0 == FALSE
var_dump(100 < TRUE); // FALSE - idéntico a (bool) 100 < TRUE
var_dump(-10 < FALSE);// FALSE - idéntico a (bool) -10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool) NULL < (bool) -100 es idéntico a FALSE < TRUE
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Transcripción de las comparaciones estándar de arrays</title>
<programlisting role="php" annotations="non-interactive">
<![CDATA[
<?php
// Los arrays son comparados de esta manera con los operadores estándar de comparación y el operador combinado
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return 1;
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>
]]>
</programlisting>
</example>
</para>
<warning>
<title>Comparación de números de punto flotante</title>
<para>
Debido a la forma en que los números de punto flotante son representados
internamente, no se debe probar la igualdad entre dos números de tipo
<type>float</type>.
</para>
<para>
Ver la documentación de <type>float</type> para más información.
</para>
</warning>
<note>
<simpara>
Tenga en cuenta que la manipulación de tipos no siempre es evidente al comparar
valores de diferentes tipos, en particular al comparar &integer;s con &boolean;s o
&integer;s con &string;s. Por lo tanto, generalmente se recomienda utilizar los
operadores de comparación <literal>===</literal> y <literal>!==</literal> en lugar de
<literal>==</literal> y <literal>!=</literal> en la mayoría de los casos.
</simpara>
</note>
<sect2 xml:id="language.operators.comparison.incomparable">
<title>Valores incomparables</title>
<simpara>
Mientras que las comparaciones de identidad (<literal>===</literal> y <literal>!==</literal>)
pueden ser aplicadas a valores arbitrarios, los otros operadores de
comparación solo deben ser aplicados a valores comparables.
El resultado de la comparación de valores incomparables es indefinido,
y no debe ser utilizado.
</simpara>
</sect2>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>strcasecmp</function></member>
<member><function>strcmp</function></member>
<member><link linkend="language.operators.array">operador de arrays</link></member>
<member><link linkend="language.types">Tipos</link></member>
</simplelist>
</para>
</sect2>
<sect2 xml:id="language.operators.comparison.ternary">
<title>El operador ternario</title>
<para>
Otro operador condicional es el operador
ternario ("?:").
<example>
<title>Asignación de un valor por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
// Ejemplo de uso para el operador ternario
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// La línea anterior es idéntica a la siguiente condición:
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
]]>
</programlisting>
</example>
La expresión <literal>(expr1) ? (expr2) : (expr3)</literal>
se evalúa a <replaceable>expr2</replaceable> si
<replaceable>expr1</replaceable> se evalúa a &true;, y
<replaceable>expr3</replaceable> si
<replaceable>expr1</replaceable> se evalúa a &false;.
</para>
<para>
Es posible omitir la parte central del operador ternario.
La expresión <literal>expr1 ?: expr3</literal> evalúa el resultado de
<replaceable>expr1</replaceable> si <replaceable>expr1</replaceable>
vale &true;, y <replaceable>expr3</replaceable> en caso contrario.
<replaceable>expr1</replaceable> solo se evalúa una vez en este caso.
</para>
<note>
<simpara>
Tenga en cuenta que el operador ternario es una expresión, y no
se evalúa como una variable, sino como el resultado de la expresión.
Es importante saberlo si se desea devolver una variable
por referencia. La instrucción
<literal>return $var == 42 ? $a : $b;</literal>
en una función devuelta por referencia no funcionará y se emitirá una alerta.
</simpara>
</note>
<note>
<para>
Se recomienda no "apilar" las expresiones ternarias.
El comportamiento de PHP al utilizar varios operadores
ternarios que no están entre paréntesis en una única expresión es
no evidente en comparación con otros lenguajes.
Anteriormente a PHP 8.0.0, el operador ternario se evaluaba
de izquierda a derecha, en lugar de derecha a izquierda como la mayoría de
los otros lenguajes de programación.
Dependiendo de la asociatividad a la izquierda es obsoleto a partir de PHP 7.4.0.
A partir de PHP 8.0.0, el operador ternario no es asociativo.
<example>
<title>Comportamiento de PHP</title>
<programlisting role="php">
<![CDATA[
<?php
// A primera vista, lo siguiente debería devolver 'true'
echo (true ? 'true' : false ? 't' : 'f');
// sin embargo, la expresión anterior devolverá 't' antes de PHP 8.0.0
// porque el operador ternario es de izquierda a derecha
// la siguiente expresión es una versión más evidente del mismo código
echo ((true ? 'true' : false) ? 't' : 'f');
// aquí, se puede observar que la primera expresión se evalúa a 'true',
// lo que hace que se evalúe a (bool)true, lo que devuelve la rama
// 'verdadera' de la segunda expresión ternaria.
?>
]]>
</programlisting>
</example>
</para>
</note>
<note>
<para>
La combinación de ternario corto (<literal>?:</literal>), sin embargo, es estable y se comporta de manera razonable.
Esto evaluará el primer argumento que evalúa a un valor no-falsy.
Tenga en cuenta que los valores indefinidos siempre emitirán un aviso.
<example>
<title>Combinación de ternario corto</title>
<programlisting role="php">
<![CDATA[
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
]]>
</programlisting>
</example>
</para>
</note>
</sect2>
<sect2 xml:id="language.operators.comparison.coalesce">
<title>Operador de fusión Null</title>
<para>
Otro operador corto útil es el operador "??" (o fusión null).
<example>
<title>Asignar un valor por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
// Ejemplo de uso para: Operador de fusión Null
$action = $_POST['action'] ?? 'default';
// el código anterior es equivalente a la siguiente estructura if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
]]>
</programlisting>
</example>
La expresión <literal>(expr1) ?? (expr2)</literal> devuelve
<replaceable>expr2</replaceable> si <replaceable>expr1</replaceable> es
&null;, y <replaceable>expr1</replaceable> en los otros casos.
</para>
<para>
En particular, este operador no emite una notificación o advertencia si
la parte izquierda no existe, exactamente como <function>isset</function>.
Esto es especialmente útil para las claves de los arrays.
</para>
<note>
<simpara>
Tenga en cuenta que el operador de fusión null es una expresión, y que
no se evalúa como una variable, sino como el resultado de una expresión.
Es importante saberlo si se desea devolver una variable
por referencia.
La expresión <literal>return $foo ?? $bar;</literal> es un retorno por
referencia que no funciona y emite una advertencia.
</simpara>
</note>
<note>
<para>
El operador de fusión null tiene una precedencia baja. Esto significa que al mezclarlo
con otros operadores (como la concatenación de strings o los operadores
aritméticos) se requerirán paréntesis.
</para>
<programlisting role="php">
<![CDATA[
<?php
// Emite una advertencia de que $name es indefinida.
print 'Mr. ' . $name ?? 'Anonymous';
// Imprime "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>
]]>
</programlisting>
</note>
<note>
<para>
Tenga en cuenta que el operador de fusión null permite una imbricación simple:
<example>
<title>Imbricación de la operación de fusión null</title>
<programlisting role="php">
<![CDATA[
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // salida 1
?>
]]>
</programlisting>
</example>
</para>
</note>
</sect2>
</sect1>