कैसे कई क्षेत्रों द्वारा वस्तुओं की एक सरणी सॉर्ट करने के लिए?


148

इस मूल प्रश्न से , मैं कई क्षेत्रों पर एक प्रकार लागू कैसे करूंगा?

इस थोड़ी अनुकूलित संरचना का उपयोग करके, मैं शहर (आरोही) और फिर मूल्य (अवरोही) कैसे छाँटूँगा?

var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

मुझे यह तथ्य पसंद आया कि एक उत्तर दिया गया था जो एक सामान्य दृष्टिकोण प्रदान करता था। जहां मैं इस कोड का उपयोग करने की योजना बना रहा हूं, मुझे तारीखों के साथ-साथ अन्य चीजों को भी छांटना होगा। ऑब्जेक्ट को "प्राइम" करने की क्षमता आसान लग रही थी, अगर थोड़ा बोझिल न हो।

मैंने इस उत्तर को एक अच्छे सामान्य उदाहरण में बनाने की कोशिश की है , लेकिन मुझे बहुत किस्मत नहीं मिल रही है।


क्या आप खोज या सॉर्ट करना चाहते हैं?
फेलिक्स क्लिंग

आपके द्वारा लिंक किए गए दूसरे उत्तर का उपयोग करने से आप वास्तव में क्या समस्या है?
कैनन

यह सामान्य नहीं है। मुझे लगता है कि जब मैं बस sort(["first-field", "ASC"], ["second-field", "DSC"]); यह कहना चाहूंगा कि मैं पहले उत्तर के "प्राइमर" तर्क में जोड़ने की कोशिश कर रहा हूं तो कोड का एक समुद्र जोड़ रहा हूं ताकि मैं तारीखों, केस-इंसिडेंसिटी आदि को संभाल सकूं
माइक

या आप प्रत्येक क्षेत्र के लिए एक वजन लागू कर सकते हैं
onmyway133

आप दर्ज कर सकते हैं checkash.com/docs/4.17.11#orderBy , अगर आप दर्ज करवाते हैं तो ठीक है
दीपांशु अरोड़ा

जवाबों:


83

एक बहु आयामी छँटाई विधि, इस उत्तर के आधार पर :

अद्यतन : यहाँ एक "अनुकूलित" संस्करण है। यह बहुत अधिक प्रीप्रोसेसिंग करता है और प्रत्येक छँटाई विकल्प के लिए पहले से एक तुलनात्मक कार्य करता है। इसे और अधिक मेमोरी की आवश्यकता हो सकती है (क्योंकि यह प्रत्येक छँटाई विकल्प के लिए एक फ़ंक्शन संग्रहीत करता है, लेकिन इसे थोड़ा बेहतर होना चाहिए क्योंकि तुलना के दौरान इसे सही सेटिंग्स निर्धारित करने की आवश्यकता नहीं है। मैंने हालांकि कोई रूपरेखा नहीं की है।

var sort_by;

(function() {
    // utility functions
    var default_cmp = function(a, b) {
            if (a == b) return 0;
            return a < b ? -1 : 1;
        },
        getCmpFunc = function(primer, reverse) {
            var dfc = default_cmp, // closer in scope
                cmp = default_cmp;
            if (primer) {
                cmp = function(a, b) {
                    return dfc(primer(a), primer(b));
                };
            }
            if (reverse) {
                return function(a, b) {
                    return -1 * cmp(a, b);
                };
            }
            return cmp;
        };

    // actual implementation
    sort_by = function() {
        var fields = [],
            n_fields = arguments.length,
            field, name, reverse, cmp;

        // preprocess sorting options
        for (var i = 0; i < n_fields; i++) {
            field = arguments[i];
            if (typeof field === 'string') {
                name = field;
                cmp = default_cmp;
            }
            else {
                name = field.name;
                cmp = getCmpFunc(field.primer, field.reverse);
            }
            fields.push({
                name: name,
                cmp: cmp
            });
        }

        // final comparison function
        return function(A, B) {
            var a, b, name, result;
            for (var i = 0; i < n_fields; i++) {
                result = 0;
                field = fields[i];
                name = field.name;

                result = field.cmp(A[name], B[name]);
                if (result !== 0) break;
            }
            return result;
        }
    }
}());

उदाहरण उपयोग:

homes.sort(sort_by('city', {name:'price', primer: parseInt, reverse: true}));

डेमो


मूल कार्य:

var sort_by = function() {
   var fields = [].slice.call(arguments),
       n_fields = fields.length;

   return function(A,B) {
       var a, b, field, key, primer, reverse, result, i;

       for(i = 0; i < n_fields; i++) {
           result = 0;
           field = fields[i];

           key = typeof field === 'string' ? field : field.name;

           a = A[key];
           b = B[key];

           if (typeof field.primer  !== 'undefined'){
               a = field.primer(a);
               b = field.primer(b);
           }

           reverse = (field.reverse) ? -1 : 1;

           if (a<b) result = reverse * -1;
           if (a>b) result = reverse * 1;
           if(result !== 0) break;
       }
       return result;
   }
};

डेमो


2
रिकॉर्ड के लिए, इस फ़ंक्शन को तर्क सूची को प्रीप्रोसेस करके और एक समान "सॉर्ट विकल्प सरणी" बनाकर सुधार किया जा सकता है। इसे पाठक के लिए व्यायाम के रूप में छोड़ दिया जाता है;)
फेलिक्स क्लिंग

@ माइक: ठीक है ... आखिरकार;) आप देख रहे हैं कि यह अब और अधिक जटिल है, क्योंकि विकल्प प्रीप्रोसेस किए गए हैं, लेकिन अंतिम तुलना फ़ंक्शन (टिप्पणी देखें) बहुत सरल है जो (उम्मीद है) बेहतर प्रदर्शन की ओर जाता है। आपके पास जितने अधिक छँटाई विकल्प हैं, इस विधि से आपको उतना ही अधिक फायदा होगा।
फेलिक्स क्लिंग

167

एक गैर-सामान्य, आपकी सटीक समस्या का सरल समाधान के लिए:

homes.sort(
   function(a, b) {          
      if (a.city === b.city) {
         // Price is only important when cities are the same
         return b.price - a.price;
      }
      return a.city > b.city ? 1 : -1;
   });

6
मुझे लगता है कि यह डेमो वही है जो ओपी चाहता है => jsfiddle.net/zJ6UA/533
अमीन जाफरी

3
यह सही विचार है, लेकिन तर्क सब गलत है। आप एक गैर-संख्यात्मक स्ट्रिंग को दूसरे स्ट्रिंग से घटा नहीं सकते हैं, और ifबयान का कोई मतलब नहीं है।
JLRishe

6
आप a.localeCompare(b)स्ट्रिंग की तुलना के लिए अंतिम पंक्ति में उपयोग कर सकते हैं ... डॉक्स देखें
माइकल पी

2
क्या पहले शहर की तुलना समानता के लिए नहीं होनी चाहिए, असमानता के लिए नहीं? दूसरे शब्दों में, क्या रेखा नहीं होनी चाहिए if (a.city === b.city)? यही है, अगर दो शहर समान हैं, तो कीमतों की तुलना करें, अन्यथा शहरों की तुलना करें।
स्टीवन रैंड

2
सबसे अच्छे जवाबों में से एक। tnx।
जोनाथन

56

जब तक यह शून्य के बराबर मूल्य तक नहीं पहुंच जाता तब तक आप मूल्यों के डेल्टा को ले कर एक जंजीर की छँटाई का उपयोग कर सकते हैं।

var data = [{ h_id: "3", city: "Dallas", state: "TX", zip: "75201", price: "162500" }, { h_id: "4", city: "Bevery Hills", state: "CA", zip: "90210", price: "319250" }, { h_id: "6", city: "Dallas", state: "TX", zip: "75000", price: "556699" }, { h_id: "5", city: "New York", state: "NY", zip: "00010", price: "962500" }];

data.sort(function (a, b) {
    return a.city.localeCompare(b.city) || b.price - a.price;
});

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

या, es6 का उपयोग करके, बस:

data.sort((a, b) => a.city.localeCompare(b.city) || b.price - a.price);

17
क्या मैं कुछ भूल रहा हूँ? 1. जो कुछ किया जा सकता है उसके लिए कोड की 60 लाइनों का उपयोग क्यों करें। सरल, स्पष्ट, संक्षिप्त। होना चाहिए स्वीकृत उत्तर IMO।
इरेज़ कोहेन

एसओ के बड़े मुद्दों में से एक यह है कि पुराने उत्तर - अक्सर नई भाषा की विशेषताओं का उपयोग करके बेहतर समाधानों से भरे होते हैं (जैसे ES5-6-7) अपने पुराने स्कोर को बनाए रखते हैं, और हम सभी को "वास्तविक" सर्वोत्तम खोजने के लिए नीचे स्क्रॉल करना होगा समाधान! एसओ को इसे संबोधित करने के लिए समय के साथ वोटों को समाप्त करना चाहिए, क्योंकि समय बीतने के साथ समस्या बहुत खराब हो रही है।
एंडी लोरेंज

53

यहाँ एक सरल कार्यात्मक दृष्टिकोण है। सरणी का उपयोग करके सॉर्ट क्रम निर्दिष्ट करें। अवरोही क्रम निर्दिष्ट करने के लिए ऋण घटाएँ ।

var homes = [
    {"h_id":"3", "city":"Dallas", "state":"TX","zip":"75201","price":"162500"},
    {"h_id":"4","city":"Bevery Hills", "state":"CA", "zip":"90210", "price":"319250"},
    {"h_id":"6", "city":"Dallas", "state":"TX", "zip":"75000", "price":"556699"},
    {"h_id":"5", "city":"New York", "state":"NY", "zip":"00010", "price":"962500"}
    ];

homes.sort(fieldSorter(['city', '-price']));
// homes.sort(fieldSorter(['zip', '-state', 'price'])); // alternative

function fieldSorter(fields) {
    return function (a, b) {
        return fields
            .map(function (o) {
                var dir = 1;
                if (o[0] === '-') {
                   dir = -1;
                   o=o.substring(1);
                }
                if (a[o] > b[o]) return dir;
                if (a[o] < b[o]) return -(dir);
                return 0;
            })
            .reduce(function firstNonZeroValue (p,n) {
                return p ? p : n;
            }, 0);
    };
}

संपादित करें: ES6 में यह बहुत छोटा है!

"use strict";
const fieldSorter = (fields) => (a, b) => fields.map(o => {
    let dir = 1;
    if (o[0] === '-') { dir = -1; o=o.substring(1); }
    return a[o] > b[o] ? dir : a[o] < b[o] ? -(dir) : 0;
}).reduce((p, n) => p ? p : n, 0);

const homes = [{"h_id":"3", "city":"Dallas", "state":"TX","zip":"75201","price":162500},     {"h_id":"4","city":"Bevery Hills", "state":"CA", "zip":"90210", "price":319250},{"h_id":"6", "city":"Dallas", "state":"TX", "zip":"75000", "price":556699},{"h_id":"5", "city":"New York", "state":"NY", "zip":"00010", "price":962500}];
const sortedHomes = homes.sort(fieldSorter(['state', '-price']));

document.write('<pre>' + JSON.stringify(sortedHomes, null, '\t') + '</pre>')


6
मुझे यह फंक्शन काफी साफ-सुथरा लगा, इसलिए मैंने पार्सर के आधार पर 90% तक के छोटे प्रदर्शन में सुधार किया। मैंने एक जिस्ट और टेस्ट सूट बनाया
php_nub_qq

नमूना डेटा यह संख्या की तरह दिखता है के आधार पर अपेक्षा के अनुरूप हल कर रहे हैं, लेकिन जब मैं कहाँ अधिक तार की तरह छँटाई इस संख्या को लागू करने की कोशिश की ... [10,100,11,9]। क्या मैं कुछ भुल गया?
मार्क कारपेंटर जूनियर

@MarkCarpenterJr। पक्का नहीं आपका क्या मतलब है। मेरे उदाहरण में संख्यात्मक प्रकार सही ढंग से हैं। क्या आप एक प्रश्न के रूप में अपने कार्यान्वयन को साझा कर सकते हैं और मुझे टिप्पणियों में संदर्भित कर सकते हैं ताकि मैं इसे देखूं? तब मैं जांच कर सकता हूं।
चिरसिकली

@MarkCarpenterJr। बस इसे देखा। मैंने टिप्पणियों में एक स्पष्टीकरण जोड़ा है।
चिरस्केली

32

मैंने आज एक बहुत ही सामान्य मल्टी फीचर सॉर्टर बनाया है। आप यहाँ पर फिर देख सकते हैं। यहाँ: https://github.com/Teun/thenBy.js

यह आपको मानक Array.sort का उपयोग करने की अनुमति देता है, लेकिन FirstBy () के साथ। तब () तब। तब () शैली। यह ऊपर पोस्ट किए गए समाधानों की तुलना में कम कोड और जटिलता है।


8
ठीक है, जब आप 3 बार कॉल करते हैं, तो 2 कॉल की गारंटी नहीं दी जाती है ताकि उन वस्तुओं के लिए पहले से अछूता हो, जहां दूसरी कॉल में कोई फर्क नहीं पड़ता है।
तीून डी

13

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

पहला तर्क ऑब्जेक्ट युक्त सरणी होना चाहिए। बाद के तर्क (ओं) को अलग-अलग ऑब्जेक्ट गुणों को संदर्भित करने वाले स्ट्रिंग्स की अल्पविराम से अलग सूची होनी चाहिए। अंतिम तर्क (जो वैकल्पिक है) केस संवेदनशील प्रकार का उपयोग करने या न करने के लिए चुनने के लिए एक बूलियन हैtrue केस संवेदी प्रकार के लिए ।

फ़ंक्शन डिफ़ॉल्ट रूप से आरोही क्रम में प्रत्येक गुण / कुंजी को सॉर्ट करेगा। यदि आप एक विशेष कुंजी को अवरोही क्रम में क्रमबद्ध करना चाहते हैं, तो इस प्रारूप में एक सरणी में पास करें:['property_name', true] :।

यहाँ एक स्पष्टीकरण के बाद फ़ंक्शन के कुछ नमूना उपयोग किए गए हैं (जहां homesएक सरणी है जिसमें ऑब्जेक्ट्स हैं):

objSort(homes, 'city') -> शहर द्वारा क्रमबद्ध (आरोही, मामला संवेदनशील)

objSort(homes, ['city', true]) -> शहर के अनुसार क्रमबद्ध (अवरोही, केस-संवेदी)

objSort(homes, 'city', true)-> शहर की तरह तो कीमत (आरोही, मामला संवेदनशील )

objSort(homes, 'city', 'price') -> शहर की तरह तो कीमत (दोनों आरोही, मामला संवेदनशील)

objSort(homes, 'city', ['price', true]) -> शहर के अनुसार (आरोही) तब मूल्य (अवरोही), केस-संवेदी)

और आगे की हलचल के बिना, यहाँ फ़ंक्शन है:

function objSort() {
    var args = arguments,
        array = args[0],
        case_sensitive, keys_length, key, desc, a, b, i;

    if (typeof arguments[arguments.length - 1] === 'boolean') {
        case_sensitive = arguments[arguments.length - 1];
        keys_length = arguments.length - 1;
    } else {
        case_sensitive = false;
        keys_length = arguments.length;
    }

    return array.sort(function (obj1, obj2) {
        for (i = 1; i < keys_length; i++) {
            key = args[i];
            if (typeof key !== 'string') {
                desc = key[1];
                key = key[0];
                a = obj1[args[i][0]];
                b = obj2[args[i][0]];
            } else {
                desc = false;
                a = obj1[args[i]];
                b = obj2[args[i]];
            }

            if (case_sensitive === false && typeof a === 'string') {
                a = a.toLowerCase();
                b = b.toLowerCase();
            }

            if (! desc) {
                if (a < b) return -1;
                if (a > b) return 1;
            } else {
                if (a > b) return -1;
                if (a < b) return 1;
            }
        }
        return 0;
    });
} //end of objSort() function

और यहाँ कुछ नमूना डेटा है:

var homes = [{
    "h_id": "3",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201",
    "price": 162500
}, {
    "h_id": "4",
    "city": "Bevery Hills",
    "state": "CA",
    "zip": "90210",
    "price": 1000000
}, {
    "h_id": "5",
    "city": "new york",
    "state": "NY",
    "zip": "00010",
    "price": 1000000
}, {
    "h_id": "6",
    "city": "Dallas",
    "state": "TX",
    "zip": "85000",
    "price": 300000
}, {
    "h_id": "7",
    "city": "New York",
    "state": "NY",
    "zip": "00020",
    "price": 345000
}];

8

यह एक पूर्ण धोखा है, लेकिन मुझे लगता है कि यह इस सवाल का मूल्य जोड़ता है क्योंकि यह मूल रूप से एक कैन्ड लाइब्रेरी फ़ंक्शन है जिसे आप आउट-ऑफ-द-बॉक्स का उपयोग कर सकते हैं।

यदि आपके कोड में एक्सेस lodashया एक लॉकेट संगत लाइब्रेरी की तरह है, underscoreतो आप _.sortByविधि का उपयोग कर सकते हैं । नीचे दिए गए स्निपेट को सीधे लॉश डॉक्यूमेंट से कॉपी किया जाता है

उदाहरणों में टिप्पणी किए गए परिणाम ऐसे लगते हैं जैसे वे सरणियों के सारणी लौटाते हैं, लेकिन यह केवल आदेश दिखा रहा है न कि वास्तविक परिणाम जो वस्तुओं की एक सरणी है।

var users = [
  { 'user': 'fred',   'age': 48 },
  { 'user': 'barney', 'age': 36 },
  { 'user': 'fred',   'age': 40 },
  { 'user': 'barney', 'age': 34 }
];

_.sortBy(users, [function(o) { return o.user; }]);
 // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]

_.sortBy(users, ['user', 'age']);
// => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]

7

यहाँ एक और वाक्य है जो शायद सिंटैक्स के लिए आपके विचार के करीब है

function sortObjects(objArray, properties /*, primers*/) {
    var primers = arguments[2] || {}; // primers are optional

    properties = properties.map(function(prop) {
        if( !(prop instanceof Array) ) {
            prop = [prop, 'asc']
        }
        if( prop[1].toLowerCase() == 'desc' ) {
            prop[1] = -1;
        } else {
            prop[1] = 1;
        }
        return prop;
    });

    function valueCmp(x, y) {
        return x > y ? 1 : x < y ? -1 : 0; 
    }

    function arrayCmp(a, b) {
        var arr1 = [], arr2 = [];
        properties.forEach(function(prop) {
            var aValue = a[prop[0]],
                bValue = b[prop[0]];
            if( typeof primers[prop[0]] != 'undefined' ) {
                aValue = primers[prop[0]](aValue);
                bValue = primers[prop[0]](bValue);
            }
            arr1.push( prop[1] * valueCmp(aValue, bValue) );
            arr2.push( prop[1] * valueCmp(bValue, aValue) );
        });
        return arr1 < arr2 ? -1 : 1;
    }

    objArray.sort(function(a, b) {
        return arrayCmp(a, b);
    });
}

// just for fun use this to reverse the city name when sorting
function demoPrimer(str) {
    return str.split('').reverse().join('');
}

// Example
sortObjects(homes, ['city', ['price', 'desc']], {city: demoPrimer});

डेमो: http://jsfiddle.net/Nq4dk/2/


संपादित करें: बस मज़े के लिए, यहाँ एक भिन्नता है जो बस एक sql जैसी स्ट्रिंग लेती है, इसलिए आप ऐसा कर सकते हैंsortObjects(homes, "city, price desc")

function sortObjects(objArray, properties /*, primers*/) {
    var primers = arguments[2] || {};

    properties = properties.split(/\s*,\s*/).map(function(prop) {
        prop = prop.match(/^([^\s]+)(\s*desc)?/i);
        if( prop[2] && prop[2].toLowerCase() === 'desc' ) {
            return [prop[1] , -1];
        } else {
            return [prop[1] , 1];
        }
    });

    function valueCmp(x, y) {
        return x > y ? 1 : x < y ? -1 : 0; 
    }

    function arrayCmp(a, b) {
        var arr1 = [], arr2 = [];
        properties.forEach(function(prop) {
            var aValue = a[prop[0]],
                bValue = b[prop[0]];
            if( typeof primers[prop[0]] != 'undefined' ) {
                aValue = primers[prop[0]](aValue);
                bValue = primers[prop[0]](bValue);
            }
            arr1.push( prop[1] * valueCmp(aValue, bValue) );
            arr2.push( prop[1] * valueCmp(bValue, aValue) );
        });
        return arr1 < arr2 ? -1 : 1;
    }

    objArray.sort(function(a, b) {
        return arrayCmp(a, b);
    });
}

यह समाधान साफ ​​है, लेकिन सरणी तुलना के कारण प्रदर्शन योग्य नहीं है। आप बस गुणों के माध्यम से एक नज़र रख सकते हैं कि तुलनात्मक मूल्य पर नज़र रखें और यह शून्य नहीं है, वापस लौटें। यह बहुत तेज है।
amankapur91

4

सरल एक:

var someArray = [...];

function generateSortFn(props) {
    return function (a, b) {
        for (var i = 0; i < props.length; i++) {
            var prop = props[i];
            var name = prop.name;
            var reverse = prop.reverse;
            if (a[name] < b[name])
                return reverse ? 1 : -1;
            if (a[name] > b[name])
                return reverse ? -1 : 1;
        }
        return 0;
    };
};

someArray.sort(generateSortFn([{name: 'prop1', reverse: true}, {name: 'prop2'}]));

3

मुझे स्नोबर्ंट का दृष्टिकोण पसंद है लेकिन शहर में समानता के लिए परीक्षण के लिए इसे एक अंतर की आवश्यकता है।

homes.sort(
   function(a,b){
      if (a.city==b.city){
         return (b.price-a.price);
      } else {
         return (a.city-b.city);
      }
   });

3

यहां एक सामान्य बहुआयामी प्रकार है, जो प्रत्येक स्तर पर उलटने और / या मानचित्रण की अनुमति देता है।

टाइपस्क्रिप्ट में लिखा है। जावास्क्रिप्ट के लिए, इस JSFiddle को देखें

कोड

type itemMap = (n: any) => any;

interface SortConfig<T> {
  key: keyof T;
  reverse?: boolean;
  map?: itemMap;
}

export function byObjectValues<T extends object>(keys: ((keyof T) | SortConfig<T>)[]): (a: T, b: T) => 0 | 1 | -1 {
  return function(a: T, b: T) {
    const firstKey: keyof T | SortConfig<T> = keys[0];
    const isSimple = typeof firstKey === 'string';
    const key: keyof T = isSimple ? (firstKey as keyof T) : (firstKey as SortConfig<T>).key;
    const reverse: boolean = isSimple ? false : !!(firstKey as SortConfig<T>).reverse;
    const map: itemMap | null = isSimple ? null : (firstKey as SortConfig<T>).map || null;

    const valA = map ? map(a[key]) : a[key];
    const valB = map ? map(b[key]) : b[key];
    if (valA === valB) {
      if (keys.length === 1) {
        return 0;
      }
      return byObjectValues<T>(keys.slice(1))(a, b);
    }
    if (reverse) {
      return valA > valB ? -1 : 1;
    }
    return valA > valB ? 1 : -1;
  };
}

उपयोग के उदाहरण

अंतिम नाम से लोगों की छंटनी करें, फिर पहला नाम:

interface Person {
  firstName: string;
  lastName: string;
}

people.sort(byObjectValues<Person>(['lastName','firstName']));

उनके नाम से भाषा कोड को क्रमबद्ध करें , न कि उनके भाषा कोड को (देखें map), फिर अवरोही संस्करण (देखें reverse) द्वारा।

interface Language {
  code: string;
  version: number;
}

// languageCodeToName(code) is defined elsewhere in code

languageCodes.sort(byObjectValues<Language>([
  {
    key: 'code',
    map(code:string) => languageCodeToName(code),
  },
  {
    key: 'version',
    reverse: true,
  }
]));

2

MULTIPLE कुंजियों के साथ ऐसा करने का एक गतिशील तरीका:

  • प्रत्येक कॉल / सॉर्ट की कुंजी से अद्वितीय मानों को फ़िल्टर करें
  • क्रम में रखना या उलट देना
  • indexOf (मान) कुंजी मानों के आधार पर प्रत्येक ऑब्जेक्ट के लिए वज़न चौड़ाई zeropad जोड़ें
  • caclutated वजन का उपयोग कर सॉर्ट करें

यहां छवि विवरण दर्ज करें

Object.defineProperty(Array.prototype, 'orderBy', {
value: function(sorts) { 
    sorts.map(sort => {            
        sort.uniques = Array.from(
            new Set(this.map(obj => obj[sort.key]))
        );

        sort.uniques = sort.uniques.sort((a, b) => {
            if (typeof a == 'string') {
                return sort.inverse ? b.localeCompare(a) : a.localeCompare(b);
            }
            else if (typeof a == 'number') {
                return sort.inverse ? (a < b) : (a > b ? 1 : 0);
            }
            else if (typeof a == 'boolean') {
                let x = sort.inverse ? (a === b) ? 0 : a? -1 : 1 : (a === b) ? 0 : a? 1 : -1;
                return x;
            }
            return 0;
        });
    });

    const weightOfObject = (obj) => {
        let weight = "";
        sorts.map(sort => {
            let zeropad = `${sort.uniques.length}`.length;
            weight += sort.uniques.indexOf(obj[sort.key]).toString().padStart(zeropad, '0');
        });
        //obj.weight = weight; // if you need to see weights
        return weight;
    }

    this.sort((a, b) => {
        return weightOfObject(a).localeCompare( weightOfObject(b) );
    });

    return this;
}
});

उपयोग:

// works with string, number and boolean
let sortered = your_array.orderBy([
    {key: "type", inverse: false}, 
    {key: "title", inverse: false},
    {key: "spot", inverse: false},
    {key: "internal", inverse: true}
]);

यहां छवि विवरण दर्ज करें


1

यहाँ @ बर्फ़ के घोल का एक सामान्य संस्करण है:

var sortarray = [{field:'city', direction:'asc'}, {field:'price', direction:'desc'}];
array.sort(function(a,b){
    for(var i=0; i<sortarray.length; i++){
        retval = a[sortarray[i].field] < b[sortarray[i].field] ? -1 : a[sortarray[i].field] > b[sortarray[i].field] ? 1 : 0;
        if (sortarray[i].direction == "desc") {
            retval = retval * -1;
        }
        if (retval !== 0) {
            return retval;
        }
    }
}


})

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

मैंने इसे 5000 रिकॉर्ड पर (वास्तव में थोड़ा और अधिक जटिल प्रकार के तर्क के साथ) परीक्षण किया और इसने पलक झपकते ही कर दिया। यदि आप वास्तव में क्लाइंट के लिए 1000 से अधिक रिकॉर्ड लोड कर रहे हैं, तो आपको संभवतः साइड-साइड सॉर्टिंग और फ़िल्टरिंग का उपयोग करना चाहिए।

यह कोड केस-सेंसिटिविटी को हैंडल नहीं कर रहा है लेकिन मैं इस तुच्छ संशोधन को संभालने के लिए इसे पाठक पर छोड़ता हूं।


1

यहाँ मेरा समाधान श्वार्ट्जियन ट्रांसफॉर्म मुहावरे पर आधारित है , आशा है कि आप इसे उपयोगी पाएंगे।

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

इसका उपयोग करने का एक उदाहरण यहां दिया गया है:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

1
मैंने इस (और अन्य पृष्ठों) पर कुछ चीजों की कोशिश की। A8m द्वारा यह समाधान केवल मेरी स्थिति के लिए काम करने के लिए एक था: gist.github.com/cemerson/f1f1434286c1262b403f3d85c96688e0
क्रिस्टोफर डी। एमर्सन

1

दूसरा रास्ता

var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];
function sortBy(ar) {
  return ar.sort((a, b) => a.city === b.city ?
      b.price.toString().localeCompare(a.price) :
      a.city.toString().localeCompare(b.city));
}
console.log(sortBy(homes));


0
function sortMultiFields(prop){
    return function(a,b){
        for(i=0;i<prop.length;i++)
        {
            var reg = /^\d+$/;
            var x=1;
            var field1=prop[i];
            if(prop[i].indexOf("-")==0)
            {
                field1=prop[i].substr(1,prop[i].length);
                x=-x;
            }

            if(reg.test(a[field1]))
            {
                a[field1]=parseFloat(a[field1]);
                b[field1]=parseFloat(b[field1]);
            }
            if( a[field1] > b[field1])
                return x;
            else if(a[field1] < b[field1])
                return -x;
        }
    }
}

यदि आप अवरोही क्रम विशेष क्षेत्र में क्रमबद्ध करना चाहते हैं तो फ़ील्ड से पहले (पुट - (माइनस) साइन का उपयोग कैसे करें )

homes.sort(sortMultiFields(["city","-price"]));

उपरोक्त फ़ंक्शन का उपयोग करके आप कई फ़ील्ड्स के साथ किसी भी json सरणी को सॉर्ट कर सकते हैं। फ़ंक्शन बॉडी को बदलने की कोई आवश्यकता नहीं है


0

@Chriskelly के उत्तर का अनुकूलन।


अधिकांश जवाब इस बात को नजरअंदाज करते हैं कि मूल्य ठीक से छंटेगा नहीं यदि मूल्य दस हजार और निचले या एक लाख से अधिक है। जेएस को वर्णानुक्रम में हल किया जा रहा है। यह यहाँ बहुत अच्छी तरह से उत्तर दिया गया था, क्यों जावास्क्रिप्ट "5, 10, 1" को सॉर्ट नहीं कर सकता है और यहाँ कैसे सही ढंग से पूर्णांक की एक सरणी को सॉर्ट करना है

अंततः हमें कुछ मूल्यांकन करना होगा यदि हम जिस क्षेत्र या नोड को छांट रहे हैं वह एक संख्या है। मैं यह नहीं कह रहा हूं कि parseInt()इस मामले में उपयोग करना सही उत्तर है, हल किए गए परिणाम अधिक महत्वपूर्ण हैं।

var homes = [{
  "h_id": "2",
  "city": "Dallas",
  "state": "TX",
  "zip": "75201",
  "price": "62500"
}, {
  "h_id": "1",
  "city": "Dallas",
  "state": "TX",
  "zip": "75201",
  "price": "62510"
}, {
  "h_id": "3",
  "city": "Dallas",
  "state": "TX",
  "zip": "75201",
  "price": "162500"
}, {
  "h_id": "4",
  "city": "Bevery Hills",
  "state": "CA",
  "zip": "90210",
  "price": "319250"
}, {
  "h_id": "6",
  "city": "Dallas",
  "state": "TX",
  "zip": "75000",
  "price": "556699"
}, {
  "h_id": "5",
  "city": "New York",
  "state": "NY",
  "zip": "00010",
  "price": "962500"
}];

homes.sort(fieldSorter(['price']));
// homes.sort(fieldSorter(['zip', '-state', 'price'])); // alternative

function fieldSorter(fields) {
  return function(a, b) {
    return fields
      .map(function(o) {
        var dir = 1;
        if (o[0] === '-') {
          dir = -1;
          o = o.substring(1);
        }
        if (!parseInt(a[o]) && !parseInt(b[o])) {
          if (a[o] > b[o]) return dir;
          if (a[o] < b[o]) return -(dir);
          return 0;
        } else {
          return dir > 0 ? a[o] - b[o] : b[o] - a[o];
        }
      })
      .reduce(function firstNonZeroValue(p, n) {
        return p ? p : n;
      }, 0);
  };
}
document.getElementById("output").innerHTML = '<pre>' + JSON.stringify(homes, null, '\t') + '</pre>';
<div id="output">

</div>


के साथ परीक्षण करने के लिए एक बेला


समस्या उस डेटा के साथ है जिसे आप सॉर्ट करना चाहते हैं। priceउदाहरण में स्ट्रिंग प्रारूप में है। यदि आप चाहते हैं कि यह मेरे उदाहरण उपयोग मानचित्र के साथ सही ढंग से काम करने के लिए पहले जिस क्षेत्र को आप संख्या स्वरूप में बदलना चाहते हैं। अर्थात्const correctedHomes = homes.map(h => ({...h, price: +h.price}))
क्रिस्चेली

0

वाह, यहाँ कुछ जटिल समाधान हैं। इसलिए जटिल मैंने कुछ सरल लेकिन बहुत शक्तिशाली के साथ आने का फैसला किया। यह रहा;

function sortByPriority(data, priorities) {
  if (priorities.length == 0) {
    return data;
  }

  const nextPriority = priorities[0];
  const remainingPriorities = priorities.slice(1);

  const matched = data.filter(item => item.hasOwnProperty(nextPriority));
  const remainingData = data.filter(item => !item.hasOwnProperty(nextPriority));

  return sortByPriority(matched, remainingPriorities)
    .sort((a, b) => (a[nextPriority] > b[nextPriority]) ? 1 : -1)
    .concat(sortByPriority(remainingData, remainingPriorities));
}

और यहाँ एक उदाहरण है कि आप इसका उपयोग कैसे करते हैं।

const data = [
  { id: 1,                         mediumPriority: 'bbb', lowestPriority: 'ggg' },
  { id: 2, highestPriority: 'bbb', mediumPriority: 'ccc', lowestPriority: 'ggg' },
  { id: 3,                         mediumPriority: 'aaa', lowestPriority: 'ggg' },
];

const priorities = [
  'highestPriority',
  'mediumPriority',
  'lowestPriority'
];


const sorted = sortByPriority(data, priorities);

यह पहले विशेषताओं की वरीयता के आधार पर छांटेगा, फिर विशेषताओं के मूल्य से।


0

यहाँ कई क्षेत्रों द्वारा सॉर्ट करने का एक एक्स्टेंसिबल तरीका है।

homes.sort(function(left, right) {
    var city_order = left.city.localeCompare(right.city);
    var price_order = parseInt(left.price) - parseInt(right.price);
    return city_order || -price_order;
});

टिप्पणियाँ

  • a.localeCompare(b)है सार्वभौमिक समर्थित और रिटर्न -1,0,1 अगर a<b, a==b, a>bक्रमशः।
  • घटाव संख्यात्मक क्षेत्रों पर काम करता है।
  • ||अंतिम पंक्ति में cityप्राथमिकता देता है price
  • किसी भी क्षेत्र में रिवर्स ऑर्डर करने के लिए, के रूप में -price_order
  • दिनांक तुलना , संख्या var date_order = new Date(left.date) - new Date(right.date);विज्ञान की तरह काम करता है क्योंकि तिथि गणित 1970 से मिलीसेकंड में बदल जाता है।
  • फ़ील्ड को श्रृंखला में जोड़ें, return city_order || -price_order || date_order;

0

मुझे लगता है कि यह करने का सबसे आसान तरीका हो सकता है।

https://coderwall.com/p/ebqhca/javascript-sort-by-two-fields

यह वास्तव में सरल है और मैंने इसे 3 अलग-अलग प्रमुख मूल्य जोड़े के साथ आजमाया और इसने बहुत अच्छा काम किया।

यहां एक सरल उदाहरण है, अधिक विवरण के लिए लिंक देखें

testSort(data) {
    return data.sort(
        a['nameOne'] > b['nameOne'] ? 1
        : b['nameOne'] > a['nameOne'] ? -1 : 0 ||
        a['date'] > b['date'] ||
        a['number'] - b['number']
    );
}

0

यहाँ आपके संदर्भ के लिए मेरा है, उदाहरण के लिए:

function msort(arr, ...compFns) {
  let fn = compFns[0];
  arr = [].concat(arr);
  let arr1 = [];
  while (arr.length > 0) {
    let arr2 = arr.splice(0, 1);
    for (let i = arr.length; i > 0;) {
      if (fn(arr2[0], arr[--i]) === 0) {
        arr2 = arr2.concat(arr.splice(i, 1));
      }
    }
    arr1.push(arr2);
  }

  arr1.sort(function (a, b) {
    return fn(a[0], b[0]);
  });

  compFns = compFns.slice(1);
  let res = [];
  arr1.map(a1 => {
    if (compFns.length > 0) a1 = msort(a1, ...compFns);
    a1.map(a2 => res.push(a2));
  });
  return res;
}

let tstArr = [{ id: 1, sex: 'o' }, { id: 2, sex: 'm' }, { id: 3, sex: 'm' }, { id: 4, sex: 'f' }, { id: 5, sex: 'm' }, { id: 6, sex: 'o' }, { id: 7, sex: 'f' }];

function tstFn1(a, b) {
  if (a.sex > b.sex) return 1;
  else if (a.sex < b.sex) return -1;
  return 0;
}

function tstFn2(a, b) {
  if (a.id > b.id) return -1;
  else if (a.id < b.id) return 1;
  return 0;
}

console.log(JSON.stringify(msort(tstArr, tstFn1, tstFn2)));
//output:
//[{"id":7,"sex":"f"},{"id":4,"sex":"f"},{"id":5,"sex":"m"},{"id":3,"sex":"m"},{"id":2,"sex":"m"},{"id":6,"sex":"o"},{"id":1,"sex":"o"}]

0

मैं कुछ इसी तरह की तलाश में था और इसके साथ समाप्त हुआ:

पहले हमारे पास एक या एक से अधिक छँटाई वाले कार्य होते हैं, हमेशा 0, 1 या -1 पर लौटते हैं:

const sortByTitle = (a, b): number => 
  a.title === b.title ? 0 : a.title > b.title ? 1 : -1;

आप जिस संपत्ति को छांटना चाहते हैं, उसके लिए आप एक-दूसरे के लिए अधिक कार्य कर सकते हैं।

फिर मेरे पास एक ऐसा फंक्शन है जो इन छँटाई कार्यों को एक में जोड़ता है:

const createSorter = (...sorters) => (a, b) =>
  sorters.reduce(
    (d, fn) => (d === 0 ? fn(a, b) : d),
    0
  );

इसका उपयोग उपरोक्त छँटाई कार्यों को पठनीय तरीके से संयोजित करने के लिए किया जा सकता है:

const sorter = createSorter(sortByTitle, sortByYear)

items.sort(sorter)

जब कोई सॉर्टिंग फ़ंक्शन 0 देता है, तो अगले सॉर्टिंग फ़ंक्शन को आगे सॉर्टिंग के लिए बुलाया जाएगा।


0

बस एक और विकल्प। निम्नलिखित उपयोगिता समारोह का उपयोग करने पर विचार करें:

/** Performs comparing of two items by specified properties
 * @param  {Array} props for sorting ['name'], ['value', 'city'], ['-date']
 * to set descending order on object property just add '-' at the begining of property
 */
export const compareBy = (...props) => (a, b) => {
  for (let i = 0; i < props.length; i++) {
    const ascValue = props[i].startsWith('-') ? -1 : 1;
    const prop = props[i].startsWith('-') ? props[i].substr(1) : props[i];
    if (a[prop] !== b[prop]) {
      return a[prop] > b[prop] ? ascValue : -ascValue;
    }
  }
  return 0;
};

उपयोग का उदाहरण (आपके मामले में):

homes.sort(compareBy('city', '-price'));

यह ध्यान दिया जाना चाहिए कि इस समारोह को और भी सामान्यीकृत किया जा सकता है ताकि नेस्टेड गुणों जैसे 'एड्रेस.सिटी' या 'स्टाइल.साइज.विक्स' आदि का उपयोग किया जा सके।


0

तुलना करने से पहले मानों को प्रारूपित करने का मौका देते हुए यह कई क्षेत्रों द्वारा सॉर्ट करने के लिए एक पुनरावर्ती एल्गोरिदम है।

var data = [
{
    "id": 1,
    "ship": null,
    "product": "Orange",
    "quantity": 7,
    "price": 92.08,
    "discount": 0
},
{
    "id": 2,
    "ship": "2017-06-14T23:00:00.000Z".toDate(),
    "product": "Apple",
    "quantity": 22,
    "price": 184.16,
    "discount": 0
},
...
]
var sorts = ["product", "quantity", "ship"]

// comp_val formats values and protects against comparing nulls/undefines
// type() just returns the variable constructor
// String.lower just converts the string to lowercase.
// String.toDate custom fn to convert strings to Date
function comp_val(value){
    if (value==null || value==undefined) return null
    var cls = type(value)
    switch (cls){
        case String:
            return value.lower()
    }
    return value
}

function compare(a, b, i){
    i = i || 0
    var prop = sorts[i]
    var va = comp_val(a[prop])
    var vb = comp_val(b[prop])

    // handle what to do when both or any values are null
    if (va == null || vb == null) return true

    if ((i < sorts.length-1) && (va == vb)) {
        return compare(a, b, i+1)
    } 
    return va > vb
}

var d = data.sort(compare);
console.log(d);

यदि ए और बी बराबर हैं तो यह अगले क्षेत्र को तब तक आजमाएगा जब तक कि कोई भी उपलब्ध न हो।


-1
homes.sort(function(a,b) { return a.city - b.city } );
homes.sort(function(a,b){
    if (a.city==b.city){
        return parseFloat(b.price) - parseFloat(a.price);
    } else {
        return 0;
    }
});

सिर्फ एक समारोह में सब कुछ क्यों नहीं रखा? यदि शहर समान नहीं है, तो उनमें से अलग लौटें, अन्यथा, कीमत अलग करें।
मैड फिजिसिस्ट

-1

यहाँ 'AffiliateDueDate' और 'शीर्षक' कॉलम हैं, दोनों को आरोही क्रम में क्रमबद्ध किया गया है।

array.sort(function(a, b) {

               if (a.AffiliateDueDate > b.AffiliateDueDate ) return 1;
               else if (a.AffiliateDueDate < b.AffiliateDueDate ) return -1;
               else if (a.Title > b.Title ) return 1;
               else if (a.Title < b.Title ) return -1;
               else return 0;
             })

-1

दो दिनांक फ़ील्ड और एक संख्यात्मक फ़ील्ड उदाहरण पर छंटनी:

var generic_date =  new Date(2070, 1, 1);
checkDate = function(date) {
  return Date.parse(date) ? new Date(date): generic_date;
}

function sortData() {  
  data.sort(function(a,b){
    var deltaEnd = checkDate(b.end) - checkDate(a.end);
    if(deltaEnd) return deltaEnd;

    var deltaRank = a.rank - b.rank;
    if (deltaRank) return deltaRank;

    var deltaStart = checkDate(b.start) - checkDate(a.start);
    if(deltaStart) return deltaStart;

    return 0;
  });
}

http://jsfiddle.net/hcWgf/57/


-1
function sort(data, orderBy) {
        orderBy = Array.isArray(orderBy) ? orderBy : [orderBy];
        return data.sort((a, b) => {
            for (let i = 0, size = orderBy.length; i < size; i++) {
                const key = Object.keys(orderBy[i])[0],
                    o = orderBy[i][key],
                    valueA = a[key],
                    valueB = b[key];
                if (!(valueA || valueB)) {
                    console.error("the objects from the data passed does not have the key '" + key + "' passed on sort!");
                    return [];
                }
                if (+valueA === +valueA) {
                    return o.toLowerCase() === 'desc' ? valueB - valueA : valueA - valueB;
                } else {
                    if (valueA.localeCompare(valueB) > 0) {
                        return o.toLowerCase() === 'desc' ? -1 : 1;
                    } else if (valueA.localeCompare(valueB) < 0) {
                        return o.toLowerCase() === 'desc' ? 1 : -1;
                    }
                }
            }
        });
    }

का उपयोग कर:

sort(homes, [{city : 'asc'}, {price: 'desc'}])


-1

इस सरल समाधान के बारे में कैसे:

const sortCompareByCityPrice = (a, b) => {
    let comparison = 0
    // sort by first criteria
    if (a.city > b.city) {
        comparison = 1
    }
    else if (a.city < b.city) {
        comparison = -1
    }
    // If still 0 then sort by second criteria descending
    if (comparison === 0) {
        if (parseInt(a.price) > parseInt(b.price)) {
            comparison = -1
        }
        else if (parseInt(a.price) < parseInt(b.price)) {
            comparison = 1
        }
    }
    return comparison 
}

इस प्रश्न के आधार पर कई (संख्या) क्षेत्रों द्वारा जावास्क्रिप्ट सॉर्ट सरणी

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