जावास्क्रिप्ट में अपने मूल्यों के साथ एक साहचर्य सरणी कैसे सॉर्ट करें?


84

मेरे पास सहयोगी सरणी है:

array["sub2"] = 1;
array["sub0"] = -1;
array["sub1"] = 0;
array["sub3"] = 1;
array["sub4"] = 0;

अपने मूल्यों द्वारा क्रमबद्ध (अवरोही) करने का सबसे सुंदर तरीका क्या है, जहां इस क्रम में संबंधित सूचकांकों के साथ एक सरणी होगी:

sub2, sub3, sub1, sub4, sub0

1
चूँकि ऑब्जेक्ट प्रॉपर्टी में कोई भाषा परिभाषित क्रम नहीं है - आप (विशेषकर जिस तरह से उन्होंने गुणों को लागू किया है, उसके आधार पर, कुछ JS इंजन में, शायद, को छोड़कर) नहीं कर सकते।
क्वेंटिन

जवाबों:


113

जावास्क्रिप्ट में "साहचर्य सरणियाँ" नहीं हैं जिस तरह से आप उनके बारे में सोच रहे हैं। इसके बजाय, आपके पास सरणी-जैसे सिंटैक्स (आपके उदाहरण के अनुसार) का उपयोग करके ऑब्जेक्ट गुण सेट करने की क्षमता है, साथ ही किसी ऑब्जेक्ट के गुणों पर पुनरावृति करने की क्षमता है।

इसका उत्थान यह है कि जिस क्रम में आप संपत्तियों पर पुनरावृत्ति करते हैं, उसकी कोई गारंटी नहीं है , इसलिए उनके लिए एक तरह का कुछ भी नहीं है। इसके बजाय, आपको अपने ऑब्जेक्ट गुणों को "ट्रू" ऐरे में बदलना होगा (जो ऑर्डर की गारंटी देता है)। यहाँ एक वस्तु को टू-टुपल्स (दो-तत्व सरणियों) के एक सरणी में बदलने के लिए एक कोड स्निपेट है, जैसा कि आप वर्णन करते हैं, उसे छांटते हुए:

var tuples = [];

for (var key in obj) tuples.push([key, obj[key]]);

tuples.sort(function(a, b) {
    a = a[1];
    b = b[1];

    return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < tuples.length; i++) {
    var key = tuples[i][0];
    var value = tuples[i][1];

    // do something with key and value
}

आपको इसे एक फ़ंक्शन में लपेटना अधिक स्वाभाविक लग सकता है जो कॉलबैक लेता है:

function bySortedValue(obj, callback, context) {
  var tuples = [];

  for (var key in obj) tuples.push([key, obj[key]]);

  tuples.sort(function(a, b) {
    return a[1] < b[1] ? 1 : a[1] > b[1] ? -1 : 0
  });

  var length = tuples.length;
  while (length--) callback.call(context, tuples[length][0], tuples[length][1]);
}

bySortedValue({
  foo: 1,
  bar: 7,
  baz: 3
}, function(key, value) {
  document.getElementById('res').innerHTML += `${key}: ${value}<br>`
});
<p id='res'>Result:<br/><br/><p>


1
tuples.sort फ़ंक्शन को tuples.sort (फ़ंक्शन (a, b) {एक [1] - b [1];}) तक साफ किया जा सकता है;
stot

2
@stot - यदि आपके मान सभी संख्याएँ हैं (जैसा कि पूछने वाले के उदाहरण में), बिल्कुल। मुझे प्रतीत होता है कि अनुपस्थित-दिमाग ने एक तुलनात्मक कार्य प्रदान किया है जो तार के साथ भी काम करता है। :-)
बेन ब्लैंक

@ बान: हाँ आप सही हैं, प्रदान किया गया संस्करण अधिक सामान्य है ;-)
स्टॉट

@, इस पोस्ट के लिए बहुत बहुत धन्यवाद। स्ट्रिंग तुलना समारोह के संबंध में, क्या यह ASCII मूल्य की तुलना का उपयोग करता है?
jjwdesign

@jjwdesign, यह मानते हुए कि स्ट्रिंग को एनकोड नहीं किया गया है, यह यूनिकोड कोड बिंदु द्वारा क्रमबद्ध होगा।
बेन ब्लैंक

85

'साहचर्य सरणी' के शब्दार्थ पर आपको सही करने के बजाय, मुझे लगता है कि आप यही चाहते हैं:

function getSortedKeys(obj) {
    var keys = keys = Object.keys(obj);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}

के लिए वास्तव में पुराने ब्राउज़र , तब इस का उपयोग करें:

function getSortedKeys(obj) {
    var keys = []; for(var key in obj) keys.push(key);
    return keys.sort(function(a,b){return obj[b]-obj[a]});
}

आप किसी ऑब्जेक्ट में (आपकी तरह) डंप करते हैं और चाबियों का एक सरणी प्राप्त करते हैं - एह गुण - पीछे, सॉर्ट किए गए अवरोही (संख्यात्मक) मान, एह, के मान, एह, ऑब्जेक्ट।

यह तभी काम करता है जब आपके मूल्य संख्यात्मक हों। function(a,b)आरोही काम करने के लिए छँटाई तंत्र को बदलने के लिए या stringमूल्यों के लिए काम करने के लिए थोड़ा उदाहरण दें (उदाहरण के लिए)। पाठक के लिए एक अभ्यास के रूप में छोड़ दिया।


1
यह पूरी तरह से काम करता है और कम कोड है तो उपरोक्त उत्तर
jshill103

1
मुझे ध्यान देना चाहिए कि आजकल अधिकांश ब्राउज़र सिर्फ Object.keys () - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
commonpike

ऑब्जेक्ट क्यों है। क्या कोई बेहतर है?
जॉन कित्जिक

1
@johnktejik यह उत्तर 2012 :-) Object.keys () आजकल एक मानक है, और इसके छोटे और शायद जल्दी था।
आमपनाई

2
... :) मैं थका हुआ था, मुझे इसे हटा दें
मनु

16

मूल्य पर एक (साहचर्य) सरणी को कैसे सॉर्ट करना है पर जारी चर्चा और अन्य समाधान ? सबसे अच्छा समाधान (मेरे मामले के लिए) saml (नीचे उद्धृत) द्वारा किया जा रहा है ।

Arrays में केवल संख्यात्मक सूचकांक हो सकते हैं। आपको इसे ऑब्जेक्ट के रूप में, या ऑब्जेक्ट के एक सरणी के रूप में फिर से लिखना होगा।

var status = new Array();
status.push({name: 'BOB', val: 10});
status.push({name: 'TOM', val: 3});
status.push({name: 'ROB', val: 22});
status.push({name: 'JON', val: 7});

यदि आपको status.pushविधि पसंद है , तो आप इसे निम्न प्रकार से कर सकते हैं:

status.sort(function(a,b) {
    return a.val - b.val;
});

अति उत्कृष्ट! नाम पर करने के लिए और अल्फा सॉर्ट करने के लिए: a.name> b.name लौटें।
मप्र

1
अल्फाबेटिक सॉर्ट के लिए, एक ही मामले में स्ट्रिंग मानों की तुलना करें क्योंकि sort()उन्हें अलग तरीके से व्यवहार करता है। इसने मुझे एक घंटे तक गड़बड़ कर दिया, जब तक कि मुझे यह स्टैकओवरफ्लो नहीं मिला ।questions / 6712034/… उदाहरण; a.name.toLowerCase() > b.name.toLowerCase()
डायलन वालडे

5

वास्तव में जावास्क्रिप्ट में "साहचर्य सरणी" जैसी कोई चीज नहीं है। आपको जो मिला है, वह सिर्फ एक पुरानी पुरानी वस्तु है। वे तरह-तरह के सहयोगी सरणियों की तरह काम करते हैं, और चाबियां उपलब्ध हैं, लेकिन चाबियों के क्रम के आसपास कोई शब्दार्थ नहीं है।

आप अपने ऑब्जेक्ट को ऑब्जेक्ट्स (की / वैल्यू पेयर) में बदल सकते हैं और सॉर्ट कर सकते हैं:

function sortObj(object, sortFunc) {
  var rv = [];
  for (var k in object) {
    if (object.hasOwnProperty(k)) rv.push({key: k, value:  object[k]});
  }
  rv.sort(function(o1, o2) {
    return sortFunc(o1.key, o2.key);
  });
  return rv;
}

फिर आप इसे एक तुलनित्र फ़ंक्शन के साथ कहेंगे।


+1 तुम मुझे हरा दो। मैं एक बहुत ही समान व्याख्या और कोड ऑफ पीस लिख रहा था।
गोंचूकी

4

यदि आप टुपल्स पसंद नहीं करते हैं, तो यहां बेन ब्लैंक के उत्तर की भिन्नता है।

यह आपको कुछ वर्ण बचाता है।

var keys = [];
for (var key in sortme) {
  keys.push(key);
}

keys.sort(function(k0, k1) {
  var a = sortme[k0];
  var b = sortme[k1];
  return a < b ? -1 : (a > b ? 1 : 0);
});

for (var i = 0; i < keys.length; ++i) {
  var key = keys[i];
  var value = sortme[key];
  // Do something with key and value.
}

4

कोई अनावश्यक जटिलता की आवश्यकता नहीं है ...

function sortMapByValue(map)
{
    var tupleArray = [];
    for (var key in map) tupleArray.push([key, map[key]]);
    tupleArray.sort(function (a, b) { return a[1] - b[1] });
    return tupleArray;
}

इसका आउटपुट एरेज़ का एक सरणी है, न कि नक्शा
डैनियल

var stuff = {"a":1 , "b":3 , "c":0 } sortMapByValue(stuff) [Array[2], Array[2], Array[2]]
डैनियल

मुझे लगता है कि यह सबसे साफ है। बस अंत में एक नक्शे में रूपांतरण जोड़ें
डैनियल

1

मैं jquery के $ .each का उपयोग करता हूं, लेकिन आप इसे लूप के साथ बना सकते हैं, एक सुधार यह है:

        //.ArraySort(array)
        /* Sort an array
         */
        ArraySort = function(array, sortFunc){
              var tmp = [];
              var aSorted=[];
              var oSorted={};

              for (var k in array) {
                if (array.hasOwnProperty(k)) 
                    tmp.push({key: k, value:  array[k]});
              }

              tmp.sort(function(o1, o2) {
                    return sortFunc(o1.value, o2.value);
              });                     

              if(Object.prototype.toString.call(array) === '[object Array]'){
                  $.each(tmp, function(index, value){
                      aSorted.push(value.value);
                  });
                  return aSorted;                     
              }

              if(Object.prototype.toString.call(array) === '[object Object]'){
                  $.each(tmp, function(index, value){
                      oSorted[value.key]=value.value;
                  });                     
                  return oSorted;
              }               
     };

तो अब आप कर सकते हैं

    console.log("ArraySort");
    var arr1 = [4,3,6,1,2,8,5,9,9];
    var arr2 = {'a':4, 'b':3, 'c':6, 'd':1, 'e':2, 'f':8, 'g':5, 'h':9};
    var arr3 = {a: 'green', b: 'brown', c: 'blue', d: 'red'};
    var result1 = ArraySort(arr1, function(a,b){return a-b});
    var result2 = ArraySort(arr2, function(a,b){return a-b});
    var result3 = ArraySort(arr3, function(a,b){return a>b});
    console.log(result1);
    console.log(result2);       
    console.log(result3);

1

मेरी राय में, यहां के विशिष्ट मामले के लिए सबसे अच्छा तरीका एक आम सुझाव है। थोड़ा सुधार मैं सुझाव दूंगा कि आधुनिक ब्राउज़रों में काम करता है:

// aao is the "associative array" you need to "sort"
Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});

यह आसानी से लागू हो सकता है और विशिष्ट मामले में शानदार काम कर सकता है ताकि आप कर सकें:

let aoo={};
aao["sub2"]=1;
aao["sub0"]=-1;
aao["sub1"]=0;
aao["sub3"]=1;
aao["sub4"]=0;

let sk=Object.keys(aao).sort(function(a,b){return aao[b]-aao[a]});

// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}

इसके अलावा, मैं यहां एक और "सामान्य" फ़ंक्शन प्रदान करता हूं जिसका उपयोग आप स्थितियों की व्यापक श्रेणी में भी सॉर्ट करने के लिए कर सकते हैं और जो सुधार मैंने मि। बेन ब्लैंक द्वारा उत्तर के दृष्टिकोण के साथ सुझाए हैं (स्ट्रिंग मान भी छाँटते हैं ) और पोप जोहानेउलियु ( विशिष्ट ऑब्जेक्ट फ़ील्ड / प्रॉपर्टी द्वारा छँटाई) और आपको यह तय करने की सुविधा देता है कि आप एक आरोही या अवरोही क्रम चाहते हैं, यहाँ यह है:

// aao := is the "associative array" you need to "sort"
// comp := is the "field" you want to compare or "" if you have no "fields" and simply need to compare values
// intVal := must be false if you need comparing non-integer values
// desc := set to true will sort keys in descendant order (default sort order is ascendant)
function sortedKeys(aao,comp="",intVal=false,desc=false){
  let keys=Object.keys(aao);
  if (comp!="") {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]-aao[a][comp]});
      else return keys.sort(function(a,b){return aao[a][comp]-aao[a][comp]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b][comp]<aao[a][comp]?1:aao[b][comp]>aao[a][comp]?-1:0});
      else return keys.sort(function(a,b){return aao[a][comp]<aao[b][comp]?1:aao[a][comp]>aao[b][comp]?-1:0});
    }
  } else {
    if (intVal) {
      if (desc) return keys.sort(function(a,b){return aao[b]-aao[a]});
      else return keys.sort(function(a,b){return aao[a]-aao[b]});
    } else {
      if (desc) return keys.sort(function(a,b){return aao[b]<aao[a]?1:aao[b]>aao[a]?-1:0});
      else return keys.sort(function(a,b){return aao[a]<aao[b]?1:aao[a]>aao[b]?-1:0});
    }
  }
}

आप निम्न कोड की तरह कुछ की कोशिश कर कार्यात्मकता का परीक्षण कर सकते हैं:

let items={};
items['Edward']=21;
items['Sharpe']=37;
items['And']=45;
items['The']=-12;
items['Magnetic']=13;
items['Zeros']=37;
//equivalent to:
//let items={"Edward": 21, "Sharpe": 37, "And": 45, "The": -12, ...};

console.log("1: "+sortedKeys(items));
console.log("2: "+sortedKeys(items,"",false,true));
console.log("3: "+sortedKeys(items,"",true,false));
console.log("4: "+sortedKeys(items,"",true,true));
/* OUTPUT
1: And,Sharpe,Zeros,Edward,Magnetic,The
2: The,Magnetic,Edward,Sharpe,Zeros,And
3: The,Magnetic,Edward,Sharpe,Zeros,And
4: And,Sharpe,Zeros,Edward,Magnetic,The
*/

items={};
items['k1']={name:'Edward',value:21};
items['k2']={name:'Sharpe',value:37};
items['k3']={name:'And',value:45};
items['k4']={name:'The',value:-12};
items['k5']={name:'Magnetic',value:13};
items['k6']={name:'Zeros',value:37};

console.log("1: "+sortedKeys(items,"name"));
console.log("2: "+sortedKeys(items,"name",false,true));
/* OUTPUT
1: k6,k4,k2,k5,k1,k3
2: k3,k1,k5,k2,k4,k6
*/

जैसा कि मैंने पहले ही कहा था, यदि आपको सामान करने की आवश्यकता है, तो आप छांटे गए कुंजियों पर लूप कर सकते हैं

let sk=sortedKeys(aoo);
// now you can loop using the sorted keys in `sk` to do stuffs
for (let i=sk.length-1;i>=0;--i){
 // do something with sk[i] or aoo[sk[i]]
}

अंतिम, लेकिन कम से कम, Object.keys और Array.sort के लिए कुछ उपयोगी संदर्भ


0

बस इतना है कि वहाँ बाहर है और कोई टपल आधारित प्रकार की तलाश में है। यह दूसरे तत्व की तुलना में, सरणी में ऑब्जेक्ट के पहले तत्व की तुलना करेगा। नीचे दिए गए उदाहरण में, यह पहले "ए", फिर "बी" और इसी तरह की तुलना करेगा।

let arr = [
    {a:1, b:2, c:3},
    {a:3, b:5, c:1},
    {a:2, b:3, c:9},
    {a:2, b:5, c:9},
    {a:2, b:3, c:10}    
]

function getSortedScore(obj) {
    var keys = []; 
    for(var key in obj[0]) keys.push(key);
    return obj.sort(function(a,b){
        for (var i in keys) {
            let k = keys[i];
            if (a[k]-b[k] > 0) return -1;
            else if (a[k]-b[k] < 0) return 1;
            else continue;
        };
    });
}

console.log(getSortedScore(arr))

ouputs

 [ { a: 3, b: 5, c: 1 },
  { a: 2, b: 5, c: 9 },
  { a: 2, b: 3, c: 10 },
  { a: 2, b: 3, c: 9 },
  { a: 1, b: 2, c: 3 } ]

-4

@ कॉमनपाइक का जवाब "सही है", लेकिन जैसा कि वह टिप्पणी पर जाता है ...

आजकल ज्यादातर ब्राउज़र सिर्फ समर्थन करते हैं Object.keys()

हाँ .. Object.keys()है रास्ता बेहतर

लेकिन इससे भी बेहतर क्या है ? यह, यह में है coffeescript!

sortedKeys = (x) -> Object.keys(x).sort (a,b) -> x[a] - x[b]

sortedKeys
  'a' :  1
  'b' :  3
  'c' :  4
  'd' : -1

[ 'd', 'a', 'b', 'c' ]

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