Existe um JavaScript strcmp ()?

127

Alguém pode verificar isso para mim? O JavaScript não possui uma versão do strcmp (), então você deve escrever algo como:

 ( str1 < str2 ) ? 
            -1 : 
             ( str1 > str2 ? 1 : 0 );
Karel Bílek
fonte
Você não está sozinho - outras pessoas já fizeram isso antes . O projeto PHP.JS também fez isso para muitas outras funções comuns. É um recurso útil.
Reed Copsey

Respostas:

134

A respeito

str1.localeCompare(str2)
newacct
fonte
localeCompare () parecia bom, mas parecia que era apenas para MS, ou não no padrão, na melhor das hipóteses.
10
que padrão você está olhando? parece ser em ECMA-262 secção padrão 15.5.4.9, bem como no Mozilla Javascript referência ( developer.mozilla.org/en/Core_JavaScript_1.5_Reference/... )
newacct
newacct está absolutamente correto. Este parece ser o padrão ECMAScript. Provavelmente a melhor solução neste caso.
coderjoe 24/07/2009
3
localeCompare()às vezes se comporta de maneira diferente em cada navegador.
Varda Elentári 23/03
1
@ VardaElentári: Apenas para personagens que não têm ordem lexical no local especificado. Para caracteres que fazem e navegadores que não restringem quais partes do Unicode eles usam, os resultados são consistentes e definidos pelo ECMA-402 e Unicode .
TJ Crowder
38

Javascript não tem, como você aponta.

Uma pesquisa rápida surgiu com:

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/

Obviamente, você pode adicionar o localeCompare, se necessário:

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

E use em str1.localeCompare(str2)qualquer lugar, sem ter que se preocupar com o envio do navegador local. O único problema é que você teria que adicionar suporte localeseoptions se você se importa com isso.

Esteban Küber
fonte
Eu acho que essa é uma boa maneira de lidar com isso (detecção de recursos e polyfill FTW), mas se o desempenho da micro velocidade é tão importante quanto à necessidade desse método, então eu estou um pouco confuso que ==é usado e não, ===pois o último evita conversão de tipo e, portanto, é esse micro segundo mais rápido.
Tokimon
uma nota sobre a localeCompare polyfill-- não diferencia maiúsculas de minúsculas, de modo a tornar o polyfill também não diferencia maiúsculas e minúsculas que você pode fazer algo como- var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Kip
22

localeCompare()é lento ; portanto, se você não se importa com a ordem "correta" de cadeias de caracteres que não sejam do inglês, tente seu método original ou a aparência mais limpa:

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

Esta é uma ordem de magnitude mais rápida do que localeCompare()na minha máquina.

Os +garante que a resposta é sempre numérico ao invés de boolean.

1 ''
fonte
Dois erros: não retorna 0 para str1 == str2, não retorna 1 para str1> str2
stackunderflow
2
@stackunderflow Estou usando com sucesso em uma função de classificação. Qual é o bug que você está enfrentando?
1 ''
1
Isso retornará -1, falso ou verdadeiro em vez de -1, 0 ou 1. Para que ele retorne números sempre, ajuste-o assim: str1 <str2? -1: + (str1> str2)
jfren484
2
Mais uma coisa (estou usando isso no código que estou escrevendo agora, por isso estou aperfeiçoando): esteja ciente de que essa é uma comparação que diferencia maiúsculas de minúsculas ('Foo' virá antes de 'bar', mas ' Bar 'virá depois de' foo '). Isso corresponde à pergunta do OP sobre strcmp, mas muitas pessoas podem vir aqui procurando uma comparação independente de caso.
precisa saber é
5
Aqui está uma expressão de aparência ainda mais limpa:(str1 > str2) - (str1 < str2)
Jonathan Gilbert
2
var strcmp = new Intl.Collator(undefined, {numeric:true, sensitivity:'base'}).compare;

Uso: strcmp(string1, string2)

Resultado: 1significa string1 é maior, 0significa igual, -1significa string2 é maior.

Isso tem desempenho superior ao String.prototype.localeCompare

Além disso, numeric:truefaz a comparação lógica de números

Anônimo
fonte
-1

E se:

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

Então, para comparar s1 com 2:

s1.strcmp(s2)
Panos Papadopoulos
fonte
1
Seria bom se você dissesse por que eles não deveriam fazer o que fizeram. Eu poderia entender se eles estavam alterando como um método de função existente funcionava, mas, neste caso, eles estão adicionando um novo.
Relaxando em Chipre
2
Estender protótipos incondicionalmente como esse geralmente é um grande não-não.
214 Christopher Christopher