¿Hay un strcmp de JavaScript ()?


Respuestas:


134

Qué pasa

str1.localeCompare(str2)

localeCompare () se veía bien, pero parecía que era solo para MS, o no en el estándar en el mejor de los casos.

10
¿Qué estándar estás mirando? parece estar en la sección estándar 15.5.4.9 de ECMA-262, así como en la referencia de Javascript de mozilla ( developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… )
newacct el

newacct es absolutamente correcto. Esto parece ser el estándar ECMAScript. Probablemente la mejor solución en este caso.
coderjoe

3
localeCompare()a veces se comporta de manera diferente en cada navegador.
Varda Elentári

1
@ VardaElentári: solo para caracteres que no tienen un orden léxico en la configuración regional dada. Para los caracteres que sí lo hacen y los navegadores que no restringen qué partes de Unicode usan, los resultados son consistentes y definidos por ECMA-402 y Unicode .
TJ Crowder

38

Javascript no lo tiene, como usted señala.

Se produjo una búsqueda rápida con:

function strcmp ( str1, str2 ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Waldo Malqui Silva
    // +      input by: Steve Hilder
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: gorthaur
    // *     example 1: strcmp( 'waldo', 'owald' );
    // *     returns 1: 1
    // *     example 2: strcmp( 'owald', 'waldo' );
    // *     returns 2: -1

    return ( ( str1 == str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );
}

de http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_strcmp/

Por supuesto, puede agregar localeCompare si es necesario:

if (typeof(String.prototype.localeCompare) === 'undefined') {
    String.prototype.localeCompare = function(str, locale, options) {
        return ((this == str) ? 0 : ((this > str) ? 1 : -1));
    };
}

Y úselo en str1.localeCompare(str2)todas partes, sin tener que preocuparse si el navegador local lo envió. El único problema es que tendrías que agregar soporte localesyoptions si te importa eso.


Creo que esta es una buena manera de manejarlo (detección de características y polyfill FTW), pero si el rendimiento de micro velocidad es tan importante, como para la necesidad de este método, entonces estoy un poco desconcertado de que ==se use y no ===porque este último evite tipo de conversión y, por lo tanto, es ese micro segundo más rápido.
Tokimon

una nota sobre el polyfill-- localeCompare no distingue entre mayúsculas y minúsculas, por lo que para que el polyfill tampoco distinga entre mayúsculas y minúsculas, puede hacer algo como- var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Kip

22

localeCompare()es lento , por lo que si no le importa el orden "correcto" de las cadenas de caracteres que no están en inglés, pruebe su método original o el aspecto más limpio:

str1 < str2 ? -1 : +(str1 > str2)

Este es un orden de magnitud más rápido que localeCompare()en mi máquina.

Esto +asegura que la respuesta sea siempre numérica en lugar de booleana.


Dos errores: no devuelve 0 para str1 == str2, no devuelve 1 para str1>
str2

2
@stackunderflow Lo estoy usando con éxito en una función de clasificación. ¿Cuál es el error que estás experimentando?
1 ''

1
Esto devolverá -1, falso o verdadero en lugar de -1, 0 o 1. Para que siempre devuelva números, modifíquelo así: str1 <str2? -1: + (str1> str2)
jfren484

2
Una cosa más (estoy usando esto en el código que estoy escribiendo ahora, así que lo he estado perfeccionando): solo tenga en cuenta que esta es una comparación entre mayúsculas y minúsculas ('Foo' vendrá antes de 'bar' pero ' Bar 'vendrá después de' foo '). Eso corresponde a la pregunta de OP sobre strcmp, pero muchas personas pueden venir aquí en busca de una comparación independiente de los casos.
jfren484

55
Aquí hay una expresión aún más limpia:(str1 > str2) - (str1 < str2)
Jonathan Gilbert

2
var strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;

Uso: strcmp(string1, string2)

Resultado: 1significa que string1 es más grande, 0significa igual, -1significa string2 es más grande.

Esto tiene un rendimiento más alto que String.prototype.localeCompare

Además, numeric:truehace que haga una comparación lógica de números



-1

Qué tal si:

String.prototype.strcmp = function(s) {
    if (this < s) return -1;
    if (this > s) return 1;
    return 0;
}

Luego, para comparar s1 con 2:

s1.strcmp(s2)

1
Sería útil que dijeras por qué no deberían hacer lo que hicieron. Podría entender si estaban alterando cómo funcionaba un método de función existente, pero en este caso están agregando uno nuevo.
Relajarse en Chipre

2
Extender prototipos incondicionalmente como este es generalmente un gran no-no.
Christopher
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.