जावास्क्रिप्ट में केस-असंवेदनशील छँटाई कैसे करें?


220

मेरे पास स्ट्रिंग की एक सरणी है जिसे मुझे जावास्क्रिप्ट में क्रमबद्ध करने की आवश्यकता है, लेकिन एक मामले में असंवेदनशील तरीके से। यह कैसे करें?

जवाबों:


404

में (लगभग :) एक-लाइनर

["Foo", "bar"].sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
});

जिसके परिणामस्वरूप

[ 'bar', 'Foo' ]

जबकि

["Foo", "bar"].sort();

का परिणाम

[ 'Foo', 'bar' ]

9
ध्यान रखें कि localeCompare के उन्नत विकल्प अभी तक सभी प्लेटफार्मों / ब्राउज़रों पर समर्थित नहीं हैं। मुझे पता है कि वे इस उदाहरण में उपयोग नहीं किए जाते हैं, लेकिन सिर्फ स्पष्टता के लिए जोड़ना चाहते हैं। अधिक जानकारी के लिए MDN देखें
Ayame__

97
आप localeCompare () को शामिल करने जा रहे हैं, तो आप सिर्फ इस्तेमाल कर सकते हैं अपने केस-संवेदी, होने की क्षमता जैसे:return a.localeCompare(b, 'en', {'sensitivity': 'base'});
माइकल डैक

2
+1 कॉल करने के लिए toLowerCase()जब localeCompareपहले से ही कुछ मामलों में डिफ़ॉल्ट रूप से ऐसा न हो । आप इसे यहां पास करने के लिए मापदंडों के बारे में अधिक पढ़ सकते हैं: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Milimetric

3
@Milimetric संदर्भित पृष्ठ के अनुरूप है, यह सुविधा कुछ ब्राउज़रों द्वारा समर्थित नहीं है (उदाहरण। IE <11 या सफारी)। यहाँ वर्णित समाधान बहुत अच्छा है, लेकिन फिर भी कुछ ब्राउज़रों के लिए बैकपोर्टिंग / पॉलीफिल की आवश्यकता होगी।
3k-

2
यदि आपके पास एक बड़ा सरणी है, तो items.sort(new Intl.Collator('en').compare)बेहतर प्रदर्शन के लिए इसका उपयोग करना समझ में आता है । (देखें MDN ।)
valtlai

60
myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

संपादित करें: कृपया ध्यान दें कि मैंने मूल रूप से प्रदर्शन को ध्यान में रखते हुए तकनीक को चित्रित करने के लिए इसे लिखा था। कृपया एक अधिक कॉम्पैक्ट समाधान के लिए @ इवान क्रेचेव को जवाब देने के लिए भी देखें।


3
यह toLowerCaseप्रत्येक स्ट्रिंग पर दो बार कॉल कर सकता है ; चर में स्ट्रिंग के निचले संस्करणों को संग्रहीत करने के लिए अधिक कुशल होगा।
याकूब

सत्य और धन्यवाद। मैंने यह स्पष्टता के साथ लिखा है, प्रदर्शन नहीं। मुझे लगता है मुझे ध्यान देना चाहिए।
रॉन टोरनेम्बे

1
@ जेकॉब उचित जवाब देने के लिए एक ही मूल समस्या है: यह संभवतः .toLowerCase()सरणी में प्रत्येक आइटम के लिए कई बार कॉल कर सकता है । उदाहरण के लिए, रिवर्स ऑर्डर में 10 आइटम सॉर्ट करते समय 45 फंक्शन की तुलना करें। var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
कुछ भी नहीं

47

इस पुराने सवाल पर फिर से विचार करने का समय है।

आपको समाधान का उपयोग नहीं करना चाहिए toLowerCase। वे अक्षम हैं और बस कुछ भाषाओं में काम नहीं करते हैं (उदाहरण के लिए तुर्की)। इसे प्राथमिकता दें:

['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))

ब्राउज़र संगतता के लिए प्रलेखन की जांच करें और sensitivityविकल्प के बारे में जानने के लिए सब कुछ है ।


1
सावधान रहें, यह सभी जावास्क्रिप्ट इंजनों में समर्थित नहीं है।
लुबोसे तुर्क

26
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a == b) return 0;
    if (a > b) return 1;
    return -1;
});

1
याreturn a === b ? 0 : a > b ? 1 : -1;
डेविन जी रोड

यह संभवतः संख्याओं का प्रतिनिधित्व करने वाले तारों के लिए इरादा के अनुसार काम नहीं करेगा । अंकगणित संचालक तार के बजाय संख्याओं के शब्दार्थ का उपयोग करेंगे। जैसे अगर हमारे पास है ["111", "33"], तो हम चाहते हैं कि वह वापस लौटे ["111", "33"]क्योंकि 1 वर्ण कोड ऑर्डरिंग में 3 से पहले आता है। हालाँकि, इस उत्तर में फ़ंक्शन वापस आ जाएगा ["33", "111"]क्योंकि संख्या संख्या 33से कम है 111
ऑस्टिन डेविस

@AustinDavis "33" > "111" === trueऔर 33 > 111 === false। यह इच्छानुसार काम करता है।
नीट द डार्क एबसोल

12

तुम भी नए प्रयोग कर सकते हैं Intl.Collator().compare, प्रति MDN यह और अधिक कुशल जब सरणियों छँटाई। नकारात्मक पक्ष यह है कि यह पुराने ब्राउज़रों द्वारा समर्थित नहीं है। एमडीएन कहता है कि यह सफारी में बिल्कुल भी समर्थित नहीं है। यह सत्यापित करने की आवश्यकता है, क्योंकि यह बताता है कि Intl.Collatorसमर्थित है।

बड़ी संख्या में तार की तुलना करते समय, जैसे कि बड़ी सरणियों को छांटना, एक Intl.Collator ऑब्जेक्ट बनाना और उसकी तुलना की गई संपत्ति द्वारा प्रदान किए गए फ़ंक्शन का उपयोग करना बेहतर होता है

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]

11

यदि आप इनपुट सरणी में तत्वों के क्रम की परवाह किए बिना उसी आदेश की गारंटी देना चाहते हैं, तो यहां एक स्थिर छँटाई है:

myArray.sort(function(a, b) {
    /* Storing case insensitive comparison */
    var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
    /* If strings are equal in case insensitive comparison */
    if (comparison === 0) {
        /* Return case sensitive comparison instead */
        return a.localeCompare(b);
    }
    /* Otherwise return result */
    return comparison;
});

5

के .sort()साथ मामले को सामान्य करें .toLowerCase()


4

आप एल्विस ऑपरेटर का उपयोग भी कर सकते हैं:

arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit'];
arr.sort(function(s1, s2){
    var l=s1.toLowerCase(), m=s2.toLowerCase();
    return l===m?0:l>m?1:-1;
});
console.log(arr);

देता है:

biscuit,Bob,charley,fudge,Fudge

हालांकि localeCompare विधि शायद ठीक है ...

नोट: एल्विस ऑपरेटर एक संक्षिप्त रूप 'टर्नेरी ऑपरेटर' है यदि इसके बाद, आमतौर पर असाइनमेंट के साथ।
यदि आप इसे देखते हैं !: बग़ल में, यह एल्विस जैसा दिखता है ...
अर्थात:

if (y) {
  x = 1;
} else {
  x = 2;
}

आप उपयोग कर सकते हैं:

x = y?1:2;

यानी जब y सत्य है, तो 1 लौटें (एक्स के असाइनमेंट के लिए), अन्यथा 2 (एक्स के असाइनमेंट के लिए) वापस करें।


5
पांडित्यपूर्ण होने के लिए, यह एल्विस ऑपरेटर नहीं है। यह सिर्फ एक बुनियादी टर्नरी ऑपरेटर है। एक सच्चा एल्विस ऑपरेटर अशक्त है, उदाहरण के लिए, इसके बजाय x = y ? y : z, आप कर सकते हैं x = y ?: z। जावास्क्रिप्ट में एक वास्तविक एल्विस ऑपरेटर नहीं है, लेकिन आप x = y || zएक समान फैशन में उपयोग कर सकते हैं ।
चार्ल्स वुड

3

अन्य उत्तर मानते हैं कि सरणी में तार हैं। मेरा तरीका बेहतर है, क्योंकि यह तब भी काम करेगा जब सरणी में अशक्त, अपरिभाषित या अन्य गैर-स्ट्रिंग हों।

var notdefined;
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm'];

myarray.sort(ignoreCase);

alert(JSON.stringify(myarray));    // show the result

function ignoreCase(a,b) {
    return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1;
}

null'Nulk' और 'एनयूएलएम' के बीच हल हो जाएगा। लेकिन undefinedवसीयत को हमेशा अंतिम रूप दिया जाएगा।


(''+notdefined) === "undefined"इसलिए यह "z" से पहले
छंटेगा

लगता है कि मुझे इसकी परिभाषा देखनी चाहिए Array.prototype.sort: क्योंकि (''+notdefined) === "undefined" वास्तव में सच के बारे में हिस्सा है ... जिसका अर्थ है कि यदि आप क्रम को उलटने के लिए सॉर्ट फ़ंक्शन में -1 और 1 को फ्लिप करते हैं, तो अपरिभाषित अभी भी अंत तक सॉर्ट करता है। सरणी प्रकार के संदर्भ के बाहर तुलना फ़ंक्शन का उपयोग करते समय (जैसा कि जब मैं इस प्रश्न पर आया था) पर विचार करना भी आवश्यक है।
मैट डब्ल्यूडब्ल्यू

और अब उस Array.prototype.sortपरिभाषा को इंगित किया है - कुछ और टिप्पणियां। सबसे पहले, इसके लिए कोई आवश्यकता नहीं है (''+a)- ECMAScript को toString()उन्हें तुलना में पारित करने से पहले तत्वों पर कॉल करने की आवश्यकता होती है। दूसरा, तथ्य यह है कि जब बराबर (लेकिन समान-लेकिन-मामले के लिए) तार की तुलना में ignoreCaseरिटर्न का 1मतलब है कि विनिर्देश परिणाम को परिभाषित नहीं करता है अगर डुप्लिकेट मान हैं (शायद कुछ अनावश्यक स्वैप के साथ ठीक होगा, मुझे लगता है)।
मैटव्यू

@MattW, यह मुझे लगता है कि undefinedएक विशेष मामला है, जो किसी भी x x के लिए <अपरिभाषित और x> अपरिभाषित दोनों झूठे हैं । यह undefinedहमेशा अंतिम होता है, क्रमबद्ध रूप से कार्यान्वयन का एक प्रतिफल है। मैंने ('' + ए) को बस ए में बदलने की कोशिश की, लेकिन यह विफल रहा। मुझे मिल गया TypeError: a.toUpperCase is not a function। तुलनात्मक रूप से कॉल करने से पहले स्पष्ट रूप toStringसे नहीं कहा जाता है।
जॉन हेंकेल

1
आह, ठीक है, यह सही समझ में आता है। तुलना के लिए कभी नहीं कहा जाता हैundefined
जॉन हेंकेल


1

स्वीकृत उत्तर के समर्थन में मैं यह जोड़ना चाहूंगा कि नीचे दिए गए फ़ंक्शन को मूल सरणी में मानों को बदलने के लिए सॉर्ट किया गया लगता है ताकि न केवल निचले मामले को सॉर्ट किया जा सके, बल्कि ऊपरी मामले के मूल्यों को भी निचले मामले में बदल दिया जाएगा। यह मेरे लिए एक समस्या है क्योंकि भले ही मैं मैरी को बगल में देखना चाहता हूं, लेकिन मैं नहीं चाहता कि पहले मूल्य मैरी के मामले को निचले मामले में बदल दिया जाए।

myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

मेरे प्रयोगों में, स्वीकृत उत्तर से निम्न कार्य सही ढंग से होते हैं लेकिन मान नहीं बदलते हैं।

["Foo", "bar"].sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
});

0

अगर आपको समझने में दिक्कत हुई तो इससे मदद मिल सकती है:

var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"];
console.log('Unordered array ---', array, '------------');

array.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    console.log("Compare '" + a + "' and '" + b + "'");

    if( a == b) {
        console.log('Comparison result, 0 --- leave as is ');
        return 0;
    }
    if( a > b) {
        console.log('Comparison result, 1 --- move '+b+' to before '+a+' ');
        return 1;
    }
    console.log('Comparison result, -1 --- move '+a+' to before '+b+' ');
    return -1;


});

console.log('Ordered array ---', array, '------------');


// return logic

/***
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
***/

http://jsfiddle.net/ianjamieson/wmxn2ram/1/


0
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if( a == b) return 0;
    if( a > b) return 1;
    return -1;
});

उपरोक्त फ़ंक्शन में, अगर हम तुलना करते हैं जब निचले मामले में दो मूल्य ए और बी होते हैं, तो हमारे पास सुंदर परिणाम नहीं होगा।

उदाहरण, अगर सरणी [ए, ए, बी, बी, सी, सी, डी, डी, ई, ई] है और हम उपरोक्त फ़ंक्शन का उपयोग करते हैं, तो हमारे पास वास्तव में वह सरणी है। यह कुछ भी नहीं बदला है।

परिणाम के लिए [ए, ए, बी, बी, सी, सी, डी, डी, ई, ई] है, हमें फिर से तुलना करनी चाहिए जब दो निचले मामले मूल्य बराबर होते हैं:

function caseInsensitiveComparator(valueA, valueB) {
    var valueALowerCase = valueA.toLowerCase();
    var valueBLowerCase = valueB.toLowerCase();

    if (valueALowerCase < valueBLowerCase) {
        return -1;
    } else if (valueALowerCase > valueBLowerCase) {
        return 1;
    } else { //valueALowerCase === valueBLowerCase
        if (valueA < valueB) {
            return -1;
        } else if (valueA > valueB) {
            return 1;
        } else {
            return 0;
        }
    }
}

-1

मैंने शीर्ष उत्तर को एक पॉलीफ़िल में लपेट दिया ताकि मैं स्ट्रिंग सरणियों पर .sortIgnoreCase () कॉल कर सकूं

// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
    Array.prototype.sortIgnoreCase = function () {
        return this.sort(function (a, b) {
            return a.toLowerCase().localeCompare(b.toLowerCase());
        });
    };
}

कृपया कभी ऐसा न करें। केवल उन चीजों के प्रोटोटाइप को संशोधित करें जो आपके पास हैं। यह भी एक पॉलीफ़िल नहीं है, क्योंकि यह ऐरे विधि ECMAScript चश्मे में कहीं नहीं है।
जो मैफेई

-2

अपने तार लपेटो / /i। आवरण को अनदेखा करने के लिए रेगेक्स का उपयोग करने का यह एक आसान तरीका है


सवाल छँटाई का है, मेल खाने का नहीं।
user4642212
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.