कैसे जावास्क्रिप्ट में तार सॉर्ट करने के लिए


344

मेरे पास ऑब्जेक्ट्स की एक सूची है जो मैं attrटाइप स्ट्रिंग के क्षेत्र के आधार पर सॉर्ट करना चाहता हूं । मैंने प्रयोग करने की कोशिश की-

list.sort(function (a, b) {
    return a.attr - b.attr
})

लेकिन पाया गया कि -जावास्क्रिप्ट में तार के साथ काम नहीं करता है। टाइप स्ट्रिंग के साथ एक विशेषता के आधार पर मैं वस्तुओं की सूची को कैसे सॉर्ट कर सकता हूं?


1
देखने JavaScript case insensitive string comparisonपर stackoverflow.com/questions/2140627/...
एड्रियन रहो

एक त्वरित "अंतर्राष्ट्रीयकृत" समाधान के लिए (केवल आंशिक रूप से मुझे लगता है क्योंकि यह दुनिया में सभी लहजे को कवर नहीं कर सकता है), आप बस लहजे को अनदेखा करना चाहते हैं, अर्थात उन्हें हटा सकते हैं। फिर केवल अपनी स्ट्रिंग की तुलना करें, stackoverflow.com/questions/990904/…Javascript : remove accents/diacritics in strings पर देखें
Adrien Be

2
मजाकिया पर्याप्त जेफ एटवुड ने खुद 2007 में इस सामान्य मुद्दे के बारे में एक ब्लॉग पोस्ट लिखा था, देखें ब्लॉग। कोडिंगहोर
एड्रियन बी

जवाबों:


620

String.prototype.localeCompareअपने उदाहरण के अनुसार प्रयोग करें :

list.sort(function (a, b) {
    return ('' + a.attr).localeCompare(b.attr);
})

हम अपवादों से बचने के लिए a.attr को एक स्ट्रिंग होने के लिए मजबूर करते हैं। Internet Explorer 6 और फ़ायरफ़ॉक्स 1 के बाद सेlocaleCompare समर्थित किया गया है । आप निम्न कोड का उपयोग भी देख सकते हैं जो किसी लोकेल का सम्मान नहीं करता है:

if (item1.attr < item2.attr)
  return -1;
if ( item1.attr > item2.attr)
  return 1;
return 0;

81
इससे पहले कि कोई भी वही जल्दबाजी करे जैसा मैंने किया, यह स्थानीय तुलना है, न कि स्थानीय कॉम।
प्रवेश

12
पहला समाधान "ए" पर "जेड" के बाद आने पर विचार करेगा लेकिन "जेड" से पहले क्योंकि यह एएससीआईआई के चरित्र पर तुलना कर रहा है। localeCompare()इस समस्या में भाग नहीं करता है, लेकिन अंकशास्त्र को नहीं समझता है, इसलिए आपको अधिकांश भाषाओं में तुलना करने के साथ ["1", "10", "2"] मिलेंगे। आप अपने यूआई सामने अंत के लिए छँटाई चाहते हैं, alphanum / प्राकृतिक तरह एल्गोरिथ्म में नज़र stackoverflow.com/questions/4340227/... या stackoverflow.com/questions/4321829/...
Dead.Rabit

2
ध्यान दें कि localeCompare()केवल आधुनिक ब्राउज़रों में समर्थित है: IE11 + लेखन के समय, डेवलपर.
mozilla.org/en-US/docs/Web/JavaScript/Reference/…

3
नहीं, मेरा मतलब है कि तालिका की पहली पंक्ति, @ एड्रियन - IE localeCompare()कई संस्करणों को वापस करने का समर्थन करती है, लेकिन संस्करण 11 तक लोकेल को निर्दिष्ट करने का समर्थन नहीं करती है । यह भी ध्यान रखें कि डेड.बिट से जुड़े प्रश्न।
शोग

3
@ Shog9 मेरा बुरा, ऐसा लगता है जैसे यह IE6 के बाद से समर्थित है! msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx पर देखें (स्क्रॉल-डाउन / लोकेलकॉमपर () विधि पर जाएँ ) । एक बात पर ध्यान दें, पुराने कार्यान्वयन में, जहां हम लोकेशन्स और ऑप्शंस तर्कों का उपयोग नहीं करते हैं (IE11 से पहले इस्तेमाल किया गया) लोकेल और सॉर्ट ऑर्डर का उपयोग पूरी तरह से कार्यान्वयन पर निर्भर है , दूसरे शब्द में: फ़ायरफ़ॉक्स, सफारी, क्रोम और IE समान क्रम में तार नहीं। कोड देखें। http://www.p/v8/issues/detail
id

166

एक अद्यतन उत्तर (अक्टूबर 2014)

मैं वास्तव में इस स्ट्रिंग प्राकृतिक सॉर्टिंग क्रम के बारे में नाराज था इसलिए मुझे इस मुद्दे की जांच करने में काफी समय लगा। आशा है कि ये आपकी मदद करेगा।

कहानी संक्षिप्त में

localeCompare()चरित्र समर्थन बदमाश है, बस इसका उपयोग करें। जैसा कि बताया गया है Shog9, आपके प्रश्न का उत्तर है:

return item1.attr.localeCompare(item2.attr);

सभी कस्टम जावास्क्रिप्ट "प्राकृतिक स्ट्रिंग सॉर्ट क्रम" कार्यान्वयन में पाए गए कीड़े

वहाँ बाहर कस्टम कार्यान्वयन का एक गुच्छा रहे हैं, स्ट्रिंग तुलना करने की कोशिश कर अधिक सटीक "प्राकृतिक स्ट्रिंग क्रम" कहा जाता है

जब इन कार्यान्वयनों के साथ "खेल" किया जाता है, तो मैंने हमेशा कुछ अजीब "प्राकृतिक सॉर्टिंग ऑर्डर" पसंद, या गलतियों (या सर्वोत्तम मामलों में चूक) पर ध्यान दिया।

आमतौर पर, विशेष वर्ण (स्थान, डैश, एम्परसैंड, ब्रैकेट, और इसी तरह) सही तरीके से संसाधित नहीं होते हैं।

फिर आप उन्हें विभिन्न स्थानों पर मिश्रित करते हुए पाएंगे, आमतौर पर यह हो सकता है:

  • कुछ अपरकेस के बीच होंगे 'Z' और लोअरकेस 'a'
  • कुछ '9' और अपरकेस 'A' के बीच होंगे
  • कुछ लोअरकेस 'z' के बाद होगा

जब किसी ने विशेष वर्णों की अपेक्षा की होगी कि एक स्थान पर सभी को एक साथ "समूहीकृत" किया जा सकता है, केवल अंतरिक्ष विशेष वर्ण को छोड़कर (जो हमेशा पहला वर्ण होगा)। यही है, या तो सभी संख्याओं से पहले, या सभी संख्याओं और अक्षरों के बीच (लोअरकेस और अपरकेस एक दूसरे के बाद "एक साथ" हो रहा है), या सभी अक्षरों के बाद।

मेरा निष्कर्ष यह है कि वे सभी एक सुसंगत आदेश प्रदान करने में विफल रहते हैं जब मैं मुश्किल से असामान्य वर्ण जोड़ना शुरू कर देता हूं (जैसे कि डैश, विस्मयादिबोधक चिह्न और इतने पर वर्णक के साथ वर्ण)।

कस्टम कार्यान्वयन पर अनुसंधान:

ब्राउज़रों के मूल "प्राकृतिक स्ट्रिंग सॉर्ट क्रम" के माध्यम से कार्यान्वयन localeCompare()

localeCompare()सबसे पुराना कार्यान्वयन (स्थान और विकल्प तर्क के बिना) IE6 + द्वारा समर्थित है, http://msdn.microsoft.com/en-us/library/ie/s4esdbwz(v=vs.94).aspx (localeCompare पर नीचे स्क्रॉल करें) देखें ) तरीका)। अंतर्निहित localeCompare()विधि छँटाई, यहाँ तक कि अंतर्राष्ट्रीय और विशेष वर्णों में बहुत बेहतर काम करती है। localeCompare()विधि का उपयोग करने में एकमात्र समस्या यह है कि "उपयोग किए जाने वाले स्थान और क्रम क्रम पूरी तरह से कार्यान्वयन पर निर्भर हैं"। दूसरे शब्दों में, जब localeCompare जैसे कि stringOne.localeCompare (stringTwo) का उपयोग करते हैं: फ़ायरफ़ॉक्स, सफारी, क्रोम और IE में स्ट्रिंग्स के लिए एक अलग तरह का क्रम है।

ब्राउज़र-देशी कार्यान्वयन पर अनुसंधान:

"स्ट्रिंग प्राकृतिक छँटाई क्रम" की कठिनाई

एक ठोस एल्गोरिथ्म को लागू करना (अर्थ: सुसंगत लेकिन एक विस्तृत श्रृंखला को कवर करना) बहुत कठिन काम है। UTF8 में 2000 से अधिक वर्ण हैं और 120 से अधिक स्क्रिप्ट (भाषाएं) शामिल हैं । अंत में, इस कार्य के लिए कुछ विनिर्देश हैं, इसे "यूनिकोड कॉलेशन एल्गोरिथ्म" कहा जाता है, जिसे http://www.unicode.org/reports/tr10/ पर पाया जा सकता है । आप इस सवाल का मैं पोस्ट पर इस बारे में अधिक जानकारी पा सकते हैं /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order

अंतिम निष्कर्ष

इसलिए जावास्क्रिप्ट कस्टम कार्यान्वयन द्वारा प्रदान किए गए समर्थन के वर्तमान स्तर को ध्यान में रखते हुए, मैं भर में आया था, हम शायद इस सभी पात्रों और लिपियों (भाषाओं) का समर्थन करने के लिए किसी भी करीबी को कुछ भी नहीं देख पाएंगे। इसलिए मैं इसके बजाय ब्राउज़रों के मूल स्थान का उपयोग करेगा () विधि। हां, इसमें सभी ब्राउज़रों में गैर-सुसंगत मधुमक्खी के नकारात्मक पहलू हैं, लेकिन बुनियादी परीक्षण से पता चलता है कि यह वर्णों की एक विस्तृत श्रृंखला को शामिल करता है, जिससे ठोस और सार्थक क्रम के आदेश मिलते हैं।

तो जैसा कि Shog9आपने बताया , आपके प्रश्न का उत्तर है:

return item1.attr.localeCompare(item2.attr);

आगे की पढाई:

शुग 9 के अच्छे जवाब के लिए धन्यवाद, जिसने मुझे "सही" दिशा में डाल दिया जो मुझे विश्वास है


38

उत्तर (आधुनिक ECMAScript में)

list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))

या

list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))

विवरण

एक नंबर के लिए एक बूलियन मूल्य कास्टिंग निम्नलिखित पैदावार:

  • true -> 1
  • false -> 0

तीन संभावित पैटर्न पर विचार करें:

  • x, y से बड़ा है: (x > y) - (y < x)-> 1 - 0->1
  • x, y: (x > y) - (y < x)-> 0 - 0-> के बराबर है0
  • x, y से छोटा है: (x > y) - (y < x)-> 0 - 1->>-1

(वैकल्पिक)

  • x, y से बड़ा है: +(x > y) || -(x < y)-> 1 || 0->1
  • x, y: +(x > y) || -(x < y)-> 0 || 0-> के बराबर है0
  • x, y से छोटा है: +(x > y) || -(x < y)-> 0 || -1->>-1

इसलिए ये लॉजिक्‍स टिपिकल सॉर्ट तुलनित्र कार्यों के बराबर हैं।

if (x == y) {
    return 0;
}
return x > y ? 1 : -1;

1
जैसा कि मैंने पहले वाले उत्तर पर टिप्पणी की थी कि इस ट्रिक का उपयोग किया गया था , कोड-केवल उत्तरों को यह समझाकर और अधिक उपयोगी बनाया जा सकता है कि वे कैसे काम करते हैं।
डैन डस्केल्सस्कु

जोड़ा गया विवरण
mpyw

क्या आप इस पर टिप्पणी कर सकते हैं कि यह लोकेलकॉम से बेहतर है या बदतर?
रण लोटेम

3
@RanLottem localeCompareऔर मानक तुलना अलग परिणाम देती है। आपको किसकी उम्मीद है? ["A", "b", "C", "d"].sort((a, b) => a.localeCompare(b))केस-असंवेदनशील वर्णानुक्रम क्रम में सॉर्ट ["A", "b", "C", "d"].sort((a, b) => (a > b) - (a < b))करता है जबकि
कोडपॉइंट

मुझे लगता है, यह एक मुख्य बिंदु है। प्रदर्शन के अंतर के बारे में कोई विचार?
रैन लोटेम

13

आपको यहां> या <और == का उपयोग करना चाहिए। तो समाधान होगा:

list.sort(function(item1, item2) {
    var val1 = item1.attr,
        val2 = item2.attr;
    if (val1 == val2) return 0;
    if (val1 > val2) return 1;
    if (val1 < val2) return -1;
});

1
एक साइड नोट पर, यह स्ट्रिंग बनाम नंबर की तुलना नहीं करेगा। उदाहरण के लिए: 'Z' <9 (झूठी), 'Z'> 9 (भी झूठी ??), 'Z' == (भी झूठी !!!!)। जावास्क्रिप्ट में सिली नाएन ...
काटो

7

नेस्टेड टर्नरी तीर फ़ंक्शन

(a,b) => (a < b ? -1 : a > b ? 1 : 0)

7

चूंकि तारों की तुलना सीधे जावास्क्रिप्ट में की जा सकती है, यह काम करेगा

list.sort(function (a, b) {
    return a.attr > b.attr ? 1: -1;
})

एक प्रकार्य फ़ंक्शन में घटाव का उपयोग केवल तब किया जाता है जब गैर वर्णानुक्रमिक (संख्यात्मक) सॉर्ट वांछित होता है और निश्चित रूप से यह किसी भी वर्ण के साथ काम नहीं करता है


6

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

से कल्पना :

Section 11.9.4   The Strict Equals Operator ( === )

The production EqualityExpression : EqualityExpression === RelationalExpression
is evaluated as follows: 
- Let lref be the result of evaluating EqualityExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating RelationalExpression.
- Let rval be GetValue(rref).
- Return the result of performing the strict equality comparison 
  rval === lval. (See 11.9.6)

तो अब हम 11.9.6 पर जाते हैं

11.9.6   The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false. 
Such a comparison is performed as follows: 
- If Type(x) is different from Type(y), return false.
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is Number, then
...
- If Type(x) is String, then return true if x and y are exactly the 
  same sequence of characters (same length and same characters in 
  corresponding positions); otherwise, return false.

बस। तर्कों के लिए लागू ट्रिपल बराबर संचालक सही है यदि तर्क तर्कों के समान हैं (समान लंबाई और समान पदों में समान वर्ण)।

इसलिए ===उन मामलों में काम करेंगे जब हम उन तारों की तुलना करने की कोशिश कर रहे हैं जो अलग-अलग स्रोतों से आए होंगे, लेकिन जो हम जानते हैं कि आखिरकार समान मूल्य होंगे - हमारे कोड में इनलाइन स्ट्रिंग्स के लिए एक सामान्य पर्याप्त परिदृश्य। उदाहरण के लिए, यदि हमारे पास एक चर नाम है connection_state, और हम यह जानना चाहते हैं कि निम्नलिखित में से कौन सा राज्य ['connecting', 'connected', 'disconnecting', 'disconnected']अभी है, तो हम सीधे इसका उपयोग कर सकते हैं ===

लेकिन वहाँ अधिक है। 11.9.4 से ऊपर, एक छोटा नोट है:

NOTE 4     
  Comparison of Strings uses a simple equality test on sequences of code 
  unit values. There is no attempt to use the more complex, semantically oriented
  definitions of character or string equality and collating order defined in the 
  Unicode specification. Therefore Strings values that are canonically equal
  according to the Unicode standard could test as unequal. In effect this 
  algorithm assumes that both Strings are already in normalized form.

हम्म। अब क्या? बाहरी रूप से प्राप्त स्ट्रिंग्स, और सबसे अधिक संभावना है, अजीब यूनिकोडी होंगे, और हमारे कोमल ===उन्हें न्याय नहीं करेंगे। localeCompareबचाव में आता है:

15.5.4.9   String.prototype.localeCompare (that)
    ...
    The actual return values are implementation-defined to permit implementers 
    to encode additional information in the value, but the function is required 
    to define a total ordering on all Strings and to return 0 when comparing
    Strings that are considered canonically equivalent by the Unicode standard. 

हम अब घर जा सकते हैं।

tl; डॉ;

जावास्क्रिप्ट में तारों की तुलना करने के लिए, उपयोग करें localeCompare; यदि आप जानते हैं कि तार में कोई गैर-एएससीआईआई घटक नहीं है क्योंकि वे हैं, उदाहरण के लिए, आंतरिक कार्यक्रम स्थिरांक, तो ===यह भी काम करता है।


0

आपके प्रारंभिक प्रश्न में आपके ऑपरेशन में, आप निम्नलिखित ऑपरेशन कर रहे हैं:

item1.attr - item2.attr

तो, यह मानते हुए कि संख्याएँ हैं (जैसे कि आइटम 1 .attr = "1", item2.attr = "2") आप अभी भी "===" ऑपरेटर (या अन्य सख्त मूल्यांकनकर्ता) का उपयोग कर सकते हैं बशर्ते कि आप प्रकार सुनिश्चित करें। निम्नलिखित काम करना चाहिए:

return parseInt(item1.attr) - parseInt(item2.attr);

यदि वे अल्फ़ान्यूमेरिक हैं, तो लोकल कॉमपेयर () का उपयोग करें।


0
list.sort(function(item1, item2){
    return +(item1.attr > item2.attr) || +(item1.attr === item2.attr) - 1;
}) 

वे नमूने कैसे काम करते हैं:

+('aaa'>'bbb')||+('aaa'==='bbb')-1
+(false)||+(false)-1
0||0-1
-1

+('bbb'>'aaa')||+('bbb'==='aaa')-1
+(true)||+(false)-1
1||0-1
1

+('aaa'>'aaa')||+('aaa'==='aaa')-1
+(false)||+(true)-1
0||1-1
0

3
कोड-केवल उत्तरों को यह समझाकर अधिक उपयोगी बनाया जा सकता है कि वे कैसे काम करते हैं।
डैन डस्केल्सस्कु

-2
<!doctype html>
<html>
<body>
<p id = "myString">zyxtspqnmdba</p>
<p id = "orderedString"></p>
<script>
var myString = document.getElementById("myString").innerHTML;
orderString(myString);
function orderString(str) {
    var i = 0;
    var myArray = str.split("");
    while (i < str.length){
        var j = i + 1;
        while (j < str.length) {
            if (myArray[j] < myArray[i]){
                var temp = myArray[i];
                myArray[i] = myArray[j];
                myArray[j] = temp;
            }
            j++;
        }
        i++;
    }
    var newString = myArray.join("");
    document.getElementById("orderedString").innerHTML = newString;
}
</script>
</body>
</html>

1
कृपया कुछ infos जोड़ें कि यह आपके उत्तर के प्रश्न को कैसे हल करने जा रहा है। कोड-केवल उत्तरों का स्वागत नहीं किया जाता है। धन्यवाद।
वेनओएस

यहाँ आप एक स्ट्रिंग के भीतर वर्णों को क्रमबद्ध करना चाहते हैं, जो कि पूछा नहीं गया है। आप "Array.sort" जैसे str.split ("") का उपयोग करके इस छँटाई को प्राप्त कर सकते हैं। सॉर्ट () .join ("")
एलेजाद्रो Xalabarder

-2
var str = ['v','a','da','c','k','l']
var b = str.join('').split('').sort().reverse().join('')
console.log(b)

हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और संभवत: अधिक वोट मिले। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। कृपया स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें, और इस बात का संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
डेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.