मेरे पास स्ट्रिंग की एक सरणी है जिसे मुझे जावास्क्रिप्ट में क्रमबद्ध करने की आवश्यकता है, लेकिन एक मामले में असंवेदनशील तरीके से। यह कैसे करें?
मेरे पास स्ट्रिंग की एक सरणी है जिसे मुझे जावास्क्रिप्ट में क्रमबद्ध करने की आवश्यकता है, लेकिन एक मामले में असंवेदनशील तरीके से। यह कैसे करें?
जवाबों:
में (लगभग :) एक-लाइनर
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
जिसके परिणामस्वरूप
[ 'bar', 'Foo' ]
जबकि
["Foo", "bar"].sort();
का परिणाम
[ 'Foo', 'bar' ]
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()जब localeCompareपहले से ही कुछ मामलों में डिफ़ॉल्ट रूप से ऐसा न हो । आप इसे यहां पास करने के लिए मापदंडों के बारे में अधिक पढ़ सकते हैं: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
संपादित करें: कृपया ध्यान दें कि मैंने मूल रूप से प्रदर्शन को ध्यान में रखते हुए तकनीक को चित्रित करने के लिए इसे लिखा था। कृपया एक अधिक कॉम्पैक्ट समाधान के लिए @ इवान क्रेचेव को जवाब देने के लिए भी देखें।
toLowerCaseप्रत्येक स्ट्रिंग पर दो बार कॉल कर सकता है ; चर में स्ट्रिंग के निचले संस्करणों को संग्रहीत करने के लिए अधिक कुशल होगा।
.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
इस पुराने सवाल पर फिर से विचार करने का समय है।
आपको समाधान का उपयोग नहीं करना चाहिए toLowerCase। वे अक्षम हैं और बस कुछ भाषाओं में काम नहीं करते हैं (उदाहरण के लिए तुर्की)। इसे प्राथमिकता दें:
['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))
ब्राउज़र संगतता के लिए प्रलेखन की जांच करें और sensitivityविकल्प के बारे में जानने के लिए सब कुछ है ।
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a == b) return 0;
if (a > b) return 1;
return -1;
});
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"], तो हम चाहते हैं कि वह वापस लौटे ["111", "33"]क्योंकि 1 वर्ण कोड ऑर्डरिंग में 3 से पहले आता है। हालाँकि, इस उत्तर में फ़ंक्शन वापस आ जाएगा ["33", "111"]क्योंकि संख्या संख्या 33से कम है 111।
"33" > "111" === trueऔर 33 > 111 === false। यह इच्छानुसार काम करता है।
तुम भी नए प्रयोग कर सकते हैं Intl.Collator().compare, प्रति MDN यह और अधिक कुशल जब सरणियों छँटाई। नकारात्मक पक्ष यह है कि यह पुराने ब्राउज़रों द्वारा समर्थित नहीं है। एमडीएन कहता है कि यह सफारी में बिल्कुल भी समर्थित नहीं है। यह सत्यापित करने की आवश्यकता है, क्योंकि यह बताता है कि Intl.Collatorसमर्थित है।
बड़ी संख्या में तार की तुलना करते समय, जैसे कि बड़ी सरणियों को छांटना, एक Intl.Collator ऑब्जेक्ट बनाना और उसकी तुलना की गई संपत्ति द्वारा प्रदान किए गए फ़ंक्शन का उपयोग करना बेहतर होता है
["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
यदि आप इनपुट सरणी में तत्वों के क्रम की परवाह किए बिना उसी आदेश की गारंटी देना चाहते हैं, तो यहां एक स्थिर छँटाई है:
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;
});
के .sort()साथ मामले को सामान्य करें .toLowerCase()।
आप एल्विस ऑपरेटर का उपयोग भी कर सकते हैं:
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 (एक्स के असाइनमेंट के लिए) वापस करें।
x = y ? y : z, आप कर सकते हैं x = y ?: z। जावास्क्रिप्ट में एक वास्तविक एल्विस ऑपरेटर नहीं है, लेकिन आप x = y || zएक समान फैशन में उपयोग कर सकते हैं ।
अन्य उत्तर मानते हैं कि सरणी में तार हैं। मेरा तरीका बेहतर है, क्योंकि यह तब भी काम करेगा जब सरणी में अशक्त, अपरिभाषित या अन्य गैर-स्ट्रिंग हों।
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मतलब है कि विनिर्देश परिणाम को परिभाषित नहीं करता है अगर डुप्लिकेट मान हैं (शायद कुछ अनावश्यक स्वैप के साथ ठीक होगा, मुझे लगता है)।
undefinedएक विशेष मामला है, जो किसी भी x x के लिए <अपरिभाषित और x> अपरिभाषित दोनों झूठे हैं । यह undefinedहमेशा अंतिम होता है, क्रमबद्ध रूप से कार्यान्वयन का एक प्रतिफल है। मैंने ('' + ए) को बस ए में बदलने की कोशिश की, लेकिन यह विफल रहा। मुझे मिल गया TypeError: a.toUpperCase is not a function। तुलनात्मक रूप से कॉल करने से पहले स्पष्ट रूप toStringसे नहीं कहा जाता है।
undefined
ES6 संस्करण:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
स्वीकृत उत्तर के समर्थन में मैं यह जोड़ना चाहूंगा कि नीचे दिए गए फ़ंक्शन को मूल सरणी में मानों को बदलने के लिए सॉर्ट किया गया लगता है ताकि न केवल निचले मामले को सॉर्ट किया जा सके, बल्कि ऊपरी मामले के मूल्यों को भी निचले मामले में बदल दिया जाएगा। यह मेरे लिए एक समस्या है क्योंकि भले ही मैं मैरी को बगल में देखना चाहता हूं, लेकिन मैं नहीं चाहता कि पहले मूल्य मैरी के मामले को निचले मामले में बदल दिया जाए।
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());
});
अगर आपको समझने में दिक्कत हुई तो इससे मदद मिल सकती है:
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.
***/
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;
}
}
}
मैंने शीर्ष उत्तर को एक पॉलीफ़िल में लपेट दिया ताकि मैं स्ट्रिंग सरणियों पर .sortIgnoreCase () कॉल कर सकूं
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}
अपने तार लपेटो / /i। आवरण को अनदेखा करने के लिए रेगेक्स का उपयोग करने का यह एक आसान तरीका है