Чи є JavaScript strcmp ()?


127

Хтось може це підтвердити для мене? У JavaScript немає версії strcmp (), тому вам доведеться виписати щось на зразок:

 ( str1 < str2 ) ? 
            -1 : 
             ( str1 > str2 ? 1 : 0 );

Ви не самотні - інші люди робили це раніше . Проект PHP.JS насправді зробив це і для багатьох інших загальних функцій. Це зручний ресурс.
Рід Копсей

Відповіді:


134

А як на рахунок

str1.localeCompare(str2)

localeCompare () виглядав добре, але виглядало так, що це лише MS або в кращому випадку не в стандарті.

10
на який стандарт ви дивитесь? це здається в стандартному розділі 15.5.4.9 ECMA-262, а також у посиланні на mozilla Javascript ( developer.mozilla.org/en/Core_JavaScript_1.5_Reference/… )
newacct

newacct абсолютно правильний. Це здається стандартом ECMAScript. Мабуть, найкраще рішення в цьому випадку.
coderjoe

3
localeCompare()іноді поводиться по-різному в кожному браузері.
Varda Elentári

1
@ VardaElentári: Тільки для символів, які не мають лексичного впорядкування в даній мові. Для символів, які роблять і браузери , які не обмежують які частини Unicode вони використовують, результати узгоджуються і визначається ECMA-402 і Unicode .
TJ Crowder

38

У JavaScript немає, як ви зазначаєте.

Швидкий пошук:

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 ) );
}

від http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_strcmp/

Звичайно, ви можете просто додати localeCompare, якщо потрібно:

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

І користуйтеся str1.localeCompare(str2)скрізь, не турбуючись про те, що місцевий веб-переглядач поставляється з ним. Єдина проблема полягає в тому, що вам доведеться додати підтримку, localesіoptions якщо ви переймаєтесь цим.


Я думаю, що це приємний спосіб поводження з ним (виявлення функцій та поліфінілятор FTW), але якщо продуктивність мікрошвидкісної настільки важлива, як для необхідності цього методу, то я трохи спантеличений тим, що ==використовується, а не ===тому, що останні уникають перетворення типу, а значить, мікросекунда швидша.
Токімон

примітка про polyfill-- localeCompare не чутливі до регістру, тому , щоб зробити polyfill також не чутливі до регістру ви могли б зробити що - то якось var a = this.toUpperCase(); var b = str.toUpperCase(); return ((a == b) ? 0 : ((a > b) ? 1 : -1));
Кіп

22

localeCompare()повільно , тому якщо вам не байдуже "правильне" впорядкування рядків, що не містять англійської мови, спробуйте свій оригінальний метод чи вигляд, що виглядає чистіше:

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

Це на порядок швидше, ніж localeCompare()на моїй машині.

У +гарантує , що відповідь завжди числовий , а не логічне значення.


Дві помилки: не повертає 0 для str1 == str2, не повертає 1 для str1> str2
stackunderflow

2
@stackunderflow Я успішно використовую його у функції сортування. Яку помилку ви відчуваєте?
1 ''

1
Це поверне -1, false або true замість -1, 0 або 1. Щоб заставити його завжди повертати числа, налаштуйте його так: str1 <str2? -1: + (str1> str2)
jfren484

2
Ще одна річ (я використовую це в коді, який я зараз пишу, тому я його вдосконалював): просто пам’ятайте, що це порівняння з урахуванням регістру ('Foo' буде перед «bar», але ' Бар 'прийде після' foo '). Це відповідає питанню ОП про strcmp, але багато людей можуть прийти сюди, шукаючи порівняльно-агностичне порівняння.
jfren484

5
Ось ще виразніше виглядає вираз:(str1 > str2) - (str1 < str2)
Джонатан Гілберт

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

Використання: strcmp(string1, string2)

Результат: 1означає, що string1 більший, 0означає рівний, -1означає, що string2 більший.

Це має більш високі показники, ніж String.prototype.localeCompare

Крім того, numeric:trueзмушує логічне порівняння чисел



-1

Як щодо:

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

Потім, щоб порівняти s1 з 2:

s1.strcmp(s2)

1
Це допоможе, якби ви сказали, чому вони не повинні робити те, що робили. Я міг би зрозуміти, якби вони змінювали, як працює існуючий метод функції, але в цьому випадку вони додають новий.
Відпочинок на Кіпрі

2
Розширення прототипів беззастережно, як це, як правило, велике "ні-ні".
Крістофер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.