मेरे पास जावास्क्रिप्ट ऑब्जेक्ट्स की एक सरणी है:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
मैं उन्हें जावास्क्रिप्ट में last_nom
के मान से कैसे क्रमबद्ध कर सकता हूं?
मुझे sort(a,b)
के बारे में पता है, लेकिन ऐसा लगता है कि यह केवल स्ट्रिंग्स और नंबरों पर काम करता है। क्या मुझे अपनी वस्तुओं में toString()
विधि जोड़ने की आवश्यकता है?
32 जवाब
अपना खुद का तुलना फ़ंक्शन लिखना काफी आसान है:
function compare( a, b ) {
if ( a.last_nom < b.last_nom ){
return -1;
}
if ( a.last_nom > b.last_nom ){
return 1;
}
return 0;
}
objs.sort( compare );
या इनलाइन (c/o Marco Demaio):
objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))
return a.last_nom.localeCompare(b.last_nom)
भी काम करेगा।
return a.value - b.value;
(एएससी)
objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)
आप एक डायनामिक सॉर्ट फ़ंक्शन भी बना सकते हैं जो आपके द्वारा पास किए गए मान के आधार पर ऑब्जेक्ट को सॉर्ट करता है:
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
तो आपके पास इस तरह की वस्तुओं की एक सरणी हो सकती है:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
... और यह तब काम करेगा जब आप करेंगे:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
असल में यह पहले से ही सवाल का जवाब देता है। नीचे भाग लिखा गया है क्योंकि कई लोगों ने मुझसे संपर्क किया, शिकायत की कि यह कई मापदंडों के साथ काम नहीं करता।
एकाधिक पैरामीटर
आप एकाधिक सॉर्ट पैरामीटर के साथ सॉर्ट फ़ंक्शन जेनरेट करने के लिए नीचे दिए गए फ़ंक्शन का उपयोग कर सकते हैं।
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
जो आपको ऐसा कुछ करने में सक्षम करेगा:
People.sort(dynamicSortMultiple("Name", "-Surname"));
उपवर्गीकरण सरणी
हमारे बीच भाग्यशाली के लिए जो ES6 का उपयोग कर सकता है, जो मूल वस्तुओं को विस्तारित करने की अनुमति देता है:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
}
यह इसे सक्षम करेगा:
MyArray.from(People).sortBy("Name", "-Surname");
ES6/ES2015 या बाद में आप इस तरह से कर सकते हैं:
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
ES6/ES2015 से पहले
objs.sort(function(a, b) {
return a.last_nom.localeCompare(b.last_nom)
});
localeCompare
की आवश्यकता नहीं है। आप मानक >
ऑपरेटर का उपयोग कर सकते हैं - जैसा कि @ muasif80 द्वारा उत्तर में उल्लेख किया गया है - stackoverflow.com/a/67992215/6908282
समझ में नहीं आता कि लोग इसे इतना जटिल क्यों बना देते हैं:
objs.sort(function(a, b){
return a.last_nom > b.last_nom;
});
सख्त इंजन के लिए:
objs.sort(function(a, b){
return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});
इसे उल्टे वर्णानुक्रम से क्रमबद्ध करने के लिए ऑपरेटर को स्वैप करें।
if(a.count == b.count) return a.name > b.name; else return a.count > b.count;
यदि आपके पास डुप्लीकेट अंतिम नाम हैं तो आप उन्हें पहले नाम से क्रमबद्ध कर सकते हैं-
obj.sort(function(a,b){
if(a.last_nom< b.last_nom) return -1;
if(a.last_nom >b.last_nom) return 1;
if(a.first_nom< b.first_nom) return -1;
if(a.first_nom >b.first_nom) return 1;
return 0;
});
b
को सरणी में a
के बाद आना चाहिए। यदि कोई धनात्मक संख्या लौटाई जाती है, तो इसका अर्थ है कि a
, b
के बाद आना चाहिए। अगर 0
लौटाया जाता है, तो इसका मतलब है कि उन्हें बराबर माना जाता है। आप हमेशा दस्तावेज़ पढ़ सकते हैं: developer.mozilla .org/en-US/docs/Web/JavaScript/Reference/…
1, 0, -1
का उपयोग करके कोड के विभिन्न स्निपेट को गुगल किया था। मुझे वह जानकारी नहीं मिल रही थी जिसकी मुझे आवश्यकता थी।
प्रोटोटाइप वंशानुक्रम का उपयोग करके इस समस्या का सरल और त्वरित समाधान:
Array.prototype.sortBy = function(p) {
return this.slice(0).sort(function(a,b) {
return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
});
}
उदाहरण / उपयोग
objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];
objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]
objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]
अपडेट करें: अब मूल सरणी को संशोधित नहीं करता है।
2018 तक बहुत छोटा और सुरुचिपूर्ण समाधान है। महज प्रयोग करें। Array.prototype.sort() .
उदाहरण:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic', value: 13 },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return a.value - b.value;
});
a.value - b.value
डेटा के विभिन्न समयों के लिए अपनाया जा सकता है। उदाहरण के लिए, रेगेक्स का उपयोग पड़ोसी स्ट्रिंग्स की प्रत्येक जोड़ी की तुलना करने के लिए किया जा सकता है।
कस्टम तुलना फ़ंक्शन का उपयोग करने के बजाय, आप कस्टम toString()
विधि के साथ एक ऑब्जेक्ट प्रकार भी बना सकते हैं (जिसे डिफ़ॉल्ट तुलना फ़ंक्शन द्वारा लागू किया जाता है):
function Person(firstName, lastName) {
this.firtName = firstName;
this.lastName = lastName;
}
Person.prototype.toString = function() {
return this.lastName + ', ' + this.firstName;
}
var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();
आप उपयोग कर सकते हैं सबसे आसान तरीका: लोदश
(https://lodash.com/docs/4.17.10#orderBy)
यह विधि _.sortBy
की तरह है, सिवाय इसके कि यह पुनरावृत्तियों के क्रमबद्ध क्रम को निर्दिष्ट करने की अनुमति देता है। यदि आदेश निर्दिष्ट नहीं हैं, तो सभी मान आरोही क्रम में क्रमबद्ध हैं। अन्यथा, अवरोही के लिए "desc" का क्रम निर्दिष्ट करें या संगत मानों के आरोही क्रम के लिए "asc" निर्दिष्ट करें।
तर्क
संग्रह (ऐरे | ऑब्जेक्ट): संग्रह को फिर से शुरू करना है। [iteratees=[_.identity]] (ऐरे [] | फंक्शन [] | ऑब्जेक्ट [] | स्ट्रिंग []): क्रमबद्ध करने के लिए पुनरावृत्त। [आदेश] (स्ट्रिंग []): पुनरावृत्तियों के क्रमबद्ध क्रम।
रिटर्न
(ऐरे): नया सॉर्ट किया गया ऐरे देता है।
var _ = require('lodash');
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"}
];
_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);
पुराना उत्तर जो सही नहीं है:
arr.sort((a, b) => a.name > b.name)
अपडेट करें
ब्यूचैम्प की टिप्पणी से:
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
अधिक पठनीय प्रारूप:
arr.sort((a, b) => {
if (a.name < b.name) return -1
return a.name > b.name ? 1 : 0
})
नेस्टेड टर्नरी के बिना:
arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))
व्याख्या: Number()
, true
को 1
और false
से 0
को कास्ट करेगा।
arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))
arr.sort((a, b) => a.name > b.name ? 1 : -1
काम क्यों नहीं करेगा? स्ट्रिंग्स के लिए मैंने परीक्षण किया है कि यह बहुत अच्छा काम करता है। यदि आप केस असंवेदनशील चाहते हैं तो a.name.toLowerCase()
और b.name.toLowerCase()
का उपयोग करें
Lodash.js (अंडरस्कोर का सुपरसेट। जेएस)
तर्क के हर साधारण टुकड़े के लिए एक ढांचा नहीं जोड़ना अच्छा है, लेकिन अच्छी तरह से परीक्षण किए गए उपयोगिता ढांचे पर भरोसा करना विकास को गति दे सकता है और बग की मात्रा को कम कर सकता है।
लोडाश बहुत साफ कोड बनाता है और अधिक कार्यात्मक प्रोग्रामिंग शैली को बढ़ावा देता है। एक झलक में यह स्पष्ट हो जाता है कि कोड का आशय क्या है।
ओपी की समस्या को इस प्रकार हल किया जा सकता है:
const sortedObjs = _.sortBy(objs, 'last_nom');
और जानकारी? उदा. हमारे पास निम्नलिखित नेस्टेड वस्तु है:
const users = [
{ 'user': {'name':'fred', 'age': 48}},
{ 'user': {'name':'barney', 'age': 36 }},
{ 'user': {'name':'wilma'}},
{ 'user': {'name':'betty', 'age': 32}}
];
अब हम पथ निर्दिष्ट करने के लिए _.property शॉर्टहैंड user.age
का उपयोग कर सकते हैं जिस संपत्ति का मिलान किया जाना चाहिए। हम उपयोगकर्ता वस्तुओं को नेस्टेड आयु संपत्ति द्वारा क्रमबद्ध करेंगे। हाँ, यह नेस्टेड संपत्ति मिलान की अनुमति देता है!
const sortedObjs = _.sortBy(users, ['user.age']);
इसे उलटना चाहते हैं? कोई दिक्कत नहीं है। _.reverse का उपयोग करें।
const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));
श्रृंखला का उपयोग करके दोनों को जोड़ना चाहते हैं?
const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();
या आप कब श्रृंखला के ऊपर प्रवाह पसंद करते हैं
const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users);
यहां कई अच्छे उत्तर हैं, लेकिन मैं यह बताना चाहूंगा कि बहुत अधिक जटिल छँटाई प्राप्त करने के लिए उन्हें बहुत सरलता से बढ़ाया जा सकता है। केवल एक चीज जो आपको करनी है वह यह है कि OR ऑपरेटर का उपयोग इस तरह के तुलना कार्यों को श्रृंखलाबद्ध करने के लिए किया जाता है:
objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )
जहां fn1
, fn2
, ... ऐसे सॉर्ट फ़ंक्शन हैं जो [-1,0,1] लौटाते हैं। इसका परिणाम "fn1 द्वारा छँटाई", "fn2 द्वारा छँटाई" है जो SQL में ORDER BY के बराबर है।
यह समाधान ||
ऑपरेटर के व्यवहार पर आधारित है जो पहली बार मूल्यांकित अभिव्यक्ति जिसे सत्य में बदला जा सकता है।
सबसे सरल फ़ॉर्म में इस तरह केवल एक इनलाइन फ़ंक्शन है:
// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )
last_nom
,first_nom
सॉर्ट ऑर्डर के साथ दो चरण होने पर ऐसा दिखेगा:
// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ||
a.first_nom.localeCompare(b.first_nom) )
एक सामान्य तुलना फ़ंक्शन कुछ इस तरह हो सकता है:
// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])
इस फ़ंक्शन को संख्यात्मक क्षेत्रों, केस सेंसिटिविटी, आर्बिटरी डेटाटाइप आदि का समर्थन करने के लिए बढ़ाया जा सकता है।
आप उन्हें प्राथमिकता के आधार पर उनका उपयोग कर सकते हैं:
// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
यहाँ मुद्दा यह है कि कार्यात्मक दृष्टिकोण के साथ शुद्ध जावास्क्रिप्ट बाहरी पुस्तकालयों या जटिल कोड के बिना आपको एक लंबा रास्ता तय कर सकता है। यह बहुत प्रभावी भी है, क्योंकि कोई स्ट्रिंग पार्सिंग करने की आवश्यकता नहीं है
उदाहरण
objs.sort(sortBy('last_nom'));
स्क्रिप्ट:
/**
* @description
* Returns a function which will sort an
* array of objects by the given key.
*
* @param {String} key
* @param {Boolean} reverse
* @return {Function}
*/
const sortBy = (key, reverse) => {
// Move smaller items towards the front
// or back of the array depending on if
// we want to sort the array in reverse
// order or not.
const moveSmaller = reverse ? 1 : -1;
// Move larger items towards the front
// or back of the array depending on if
// we want to sort the array in reverse
// order or not.
const moveLarger = reverse ? -1 : 1;
/**
* @param {*} a
* @param {*} b
* @return {Number}
*/
return (a, b) => {
if (a[key] < b[key]) {
return moveSmaller;
}
if (a[key] > b[key]) {
return moveLarger;
}
return 0;
};
};
1, 0, -1
का उपयोग क्रमबद्ध करने के लिए क्यों किया जाता है। यहां तक कि ऊपर आपके स्पष्टीकरण के साथ, जो बहुत अच्छा लग रहा है-- मैं अभी भी इसे पूरी तरह समझ नहीं पा रहा हूं। मैं हमेशा -1
के बारे में सोचता हूं जैसे सरणी लंबाई संपत्ति का उपयोग करते समय, यानी: arr.length = -1
का अर्थ है कि आइटम नहीं मिला है। मैं शायद यहां चीजों को मिला रहा हूं, लेकिन क्या आप मुझे यह समझने में मदद कर सकते हैं कि अंक 1, 0, -1
का उपयोग क्रम निर्धारित करने के लिए क्यों किया जाता है? धन्यवाद।
a
और b
की तुलना में, यदि a
b
से बड़ा है a
के सूचकांक में 1 और इसे b
के पीछे रखें, यदि a
b
से कम है, तो a
से 1 घटाएं और b
के सामने रखें। b
. यदि a
और b
समान हैं, तो a
में 0 जोड़ें और इसे वहीं छोड़ दें।
मैंने इस विशेष दृष्टिकोण का सुझाव नहीं देखा है, इसलिए यहां एक संक्षिप्त तुलना विधि है जिसका उपयोग मैं string
और number
दोनों प्रकारों के लिए करना चाहता हूं:
const objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
const sortBy = fn => {
const cmp = (a, b) => -(a < b) || +(a > b);
return (a, b) => cmp(fn(a), fn(b));
};
const getLastName = o => o.last_nom;
const sortByLastName = sortBy(getLastName);
objs.sort(sortByLastName);
console.log(objs.map(getLastName));
sortBy()
की व्याख्या
sortBy()
एक fn
स्वीकार करता है जो तुलना में उपयोग करने के लिए किसी ऑब्जेक्ट से एक मान का चयन करता है, और एक फ़ंक्शन देता है जिसे Array.prototype.sort()
। इस उदाहरण में, हम o.last_nom
की तुलना कर रहे हैं। जब भी हमें दो वस्तुएँ प्राप्त होती हैं जैसे
a = { first_nom: 'Lazslo', last_nom: 'Jamf' }
b = { first_nom: 'Pig', last_nom: 'Bodine' }
हम उनकी तुलना (a, b) => cmp(fn(a), fn(b))
से करते हैं। मान लें कि
fn = o => o.last_nom
हम तुलना फ़ंक्शन को (a, b) => cmp(a.last_nom, b.last_nom)
तक बढ़ा सकते हैं। जिस तरह से लॉजिकल OR (||
) जावास्क्रिप्ट में काम करता है, cmp(a.last_nom, b.last_nom)
बराबर है
if (a.last_nom < b.last_nom) return -1;
if (a.last_nom > b.last_nom) return 1;
return 0;
संयोग से, इसे अन्य भाषाओं में तीन-तरफा तुलना "स्पेसशिप" (<=>
) ऑपरेटर कहा जाता है।
अंत में, यहाँ तीर फ़ंक्शंस का उपयोग किए बिना ES5-संगत सिंटैक्स है:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
function sortBy(fn) {
function cmp(a, b) { return -(a < b) || +(a > b); }
return function (a, b) { return cmp(fn(a), fn(b)); };
}
function getLastName(o) { return o.last_nom; }
var sortByLastName = sortBy(getLastName);
objs.sort(sortByLastName);
console.log(objs.map(getLastName));
-(fa < fb) || +(fa > fb)
के शॉर्टहैंड का उपयोग करना यहां एक गलती है। कोड की एक पंक्ति में संघनित होने वाले कई कथन हैं। विकल्प, एक if
कथन के साथ लिखा गया है, जो काफी संक्षिप्त होते हुए भी अधिक पठनीय होगा। मुझे लगता है कि सुंदरता के लिए पठनीयता का त्याग करना एक गलती है।
const cmp = (a, b) => -(a < b) || +(a > b);
) के साथ ठीक से काम करेगा ["ä", "a", "c", "b"].sort(cmp)
=> ["a", "b", "c", "ä"]
के बारे में सोचें, जहां ä
को अंत तक धकेला गया है। इसके बजाय आपको शायद तुलना फ़ंक्शन को अपडेट करना चाहिए: const cmp = (a, b) => a.localeCompare(b);
=> ["a", "ä", "b", "c"]
चीयर्स और उत्तर के लिए धन्यवाद ;-)
localeCompare
में बदलने से संख्याओं को क्रमबद्ध करने की क्षमता समाप्त हो जाती है, और यह काफी धीमा भी है।
मुझे पता है कि यह प्रश्न बहुत पुराना है, लेकिन मुझे मेरे जैसा कोई कार्यान्वयन नहीं दिखाई दिया।
यह संस्करण श्वार्ट्ज़ियन ट्रांसफ़ॉर्म मुहावरे पर आधारित है।
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: 'Mashraki', 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'));
वस्तुओं की जटिल सरणियों को छाँटना (अधिक)
चूंकि आप शायद इस सरणी जैसी अधिक जटिल डेटा संरचनाओं का सामना करते हैं, इसलिए मैं समाधान का विस्तार करूंगा।
टीएल; डीआर
@ege-Özcan पर आधारित अधिक प्लग करने योग्य संस्करण हैं उत्तर।
संकट
मैंने नीचे का सामना किया और इसे बदल नहीं सका। मैं भी वस्तु को अस्थायी रूप से समतल नहीं करना चाहता था। न ही मैं अंडरस्कोर / लॉश का उपयोग करना चाहता था, मुख्य रूप से प्रदर्शन कारणों और इसे स्वयं लागू करने के लिए।
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
लक्ष्य
लक्ष्य इसे प्राथमिक रूप से People.Name.name
द्वारा और दूसरा People.Name.surname
द्वारा क्रमबद्ध करना है
बाधाएं
अब, बेस समाधान में गतिशील रूप से सॉर्ट करने के लिए गुणों की गणना करने के लिए ब्रैकेट नोटेशन का उपयोग करता है। यहां, हालांकि, हमें गतिशील रूप से भी ब्रैकेट नोटेशन का निर्माण करना होगा, क्योंकि आप उम्मीद करेंगे कि People['Name.name']
जैसे कुछ काम करेंगे - जो नहीं करता है।
दूसरी ओर, केवल People['Name']['name']
करना स्थिर है और केवल आपको n-वें स्तर से नीचे जाने की अनुमति देता है।
समाधान
यहां मुख्य जोड़ ऑब्जेक्ट ट्री के नीचे चलना होगा और अंतिम पत्ते के मूल्य को निर्धारित करना होगा, साथ ही साथ किसी भी मध्यस्थ पत्ते को भी निर्दिष्ट करना होगा।
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
// { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
// { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]
// same logic as above, but strong deviation for dynamic properties
function dynamicSort(properties) {
var sortOrder = 1;
// determine sort order by checking sign of last element of array
if(properties[properties.length - 1][0] === "-") {
sortOrder = -1;
// Chop off sign
properties[properties.length - 1] = properties[properties.length - 1].substr(1);
}
return function (a,b) {
propertyOfA = recurseObjProp(a, properties)
propertyOfB = recurseObjProp(b, properties)
var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
return result * sortOrder;
};
}
/**
* Takes an object and recurses down the tree to a target leaf and returns it value
* @param {Object} root - Object to be traversed.
* @param {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
* @param {Number} index - Must not be set, since it is implicit.
* @return {String|Number} The property, which is to be compared by sort.
*/
function recurseObjProp(root, leafs, index) {
index ? index : index = 0
var upper = root
// walk down one level
lower = upper[leafs[index]]
// Check if last leaf has been hit by having gone one step too far.
// If so, return result from last step.
if (!lower) {
return upper
}
// Else: recurse!
index++
// HINT: Bug was here, for not explicitly returning function
// https://stackoverflow.com/a/17528613/3580261
return recurseObjProp(lower, leafs, index)
}
/**
* Multi-sort your array by a set of properties
* @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
* @return {Number} Number - number for sort algorithm
*/
function dynamicMultiSort() {
var args = Array.prototype.slice.call(arguments); // slight deviation to base
return function (a, b) {
var i = 0, result = 0, numberOfProperties = args.length;
// REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
// Consider: `.forEach()`
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(args[i])(a, b);
i++;
}
return result;
}
}
उदाहरण
कार्य उदाहरण JSBin पर
एक और विकल्प:
var someArray = [...];
function generateSortFn(prop, reverse) {
return function (a, b) {
if (a[prop] < b[prop]) return reverse ? 1 : -1;
if (a[prop] > b[prop]) return reverse ? -1 : 1;
return 0;
};
}
someArray.sort(generateSortFn('name', true));
डिफ़ॉल्ट रूप से आरोही प्रकार।
एक आसान तरीका:
objs.sort(function(a,b) {
return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
देखें कि त्रुटियों को रोकने के लिए '.toLowerCase()'
आवश्यक है तार की तुलना में।
objs.sort( (a,b) => b.last_nom.toLowerCase() < a.last_nom.toLowerCase() );
Ege zcan कोड . के लिए अतिरिक्त विवरण पैराम्स
function dynamicSort(property, desc) {
if (desc) {
return function (a, b) {
return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
}
}
return function (a, b) {
return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
}
}
विनय के विचार के साथ ईजी के गतिशील समाधान का संयोजन, आपको एक अच्छा मजबूत समाधान मिलता है:
Array.prototype.sortBy = function() {
function _sortByAttr(attr) {
var sortOrder = 1;
if (attr[0] == "-") {
sortOrder = -1;
attr = attr.substr(1);
}
return function(a, b) {
var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
return result * sortOrder;
}
}
function _getSortFunc() {
if (arguments.length == 0) {
throw "Zero length arguments not allowed for Array.sortBy()";
}
var args = arguments;
return function(a, b) {
for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
result = _sortByAttr(args[i])(a, b);
}
return result;
}
}
return this.sort(_getSortFunc.apply(null, arguments));
}
उपयोग:
// Utility for printing objects
Array.prototype.print = function(title) {
console.log("************************************************************************");
console.log("**** "+title);
console.log("************************************************************************");
for (var i = 0; i < this.length; i++) {
console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
}
}
// Setup sample data
var arrObj = [
{FirstName: "Zach", LastName: "Emergency", Age: 35},
{FirstName: "Nancy", LastName: "Nurse", Age: 27},
{FirstName: "Ethel", LastName: "Emergency", Age: 42},
{FirstName: "Nina", LastName: "Nurse", Age: 48},
{FirstName: "Anthony", LastName: "Emergency", Age: 44},
{FirstName: "Nina", LastName: "Nurse", Age: 32},
{FirstName: "Ed", LastName: "Emergency", Age: 28},
{FirstName: "Peter", LastName: "Physician", Age: 58},
{FirstName: "Al", LastName: "Emergency", Age: 51},
{FirstName: "Ruth", LastName: "Registration", Age: 62},
{FirstName: "Ed", LastName: "Emergency", Age: 38},
{FirstName: "Tammy", LastName: "Triage", Age: 29},
{FirstName: "Alan", LastName: "Emergency", Age: 60},
{FirstName: "Nina", LastName: "Nurse", Age: 54}
];
//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");
एक साधारण कार्य जो किसी संपत्ति द्वारा वस्तु की एक सरणी को सॉर्ट करता है
function sortArray(array, property, direction) {
direction = direction || 1;
array.sort(function compare(a, b) {
let comparison = 0;
if (a[property] > b[property]) {
comparison = 1 * direction;
} else if (a[property] < b[property]) {
comparison = -1 * direction;
}
return comparison;
});
return array; // Chainable
}
उपयोग:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc
अपने उदाहरण के अनुसार, आपको दो क्षेत्रों (अंतिम नाम, प्रथम नाम) के आधार पर क्रमबद्ध करना होगा, न कि एक। इस प्रकार को एक पंक्ति में बनाने के लिए आप Alasql लाइब्रेरी का उपयोग कर सकते हैं:
var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);
इस उदाहरण को jsFiddle पर आज़माएं।
चेतावनी!
इस समाधान का उपयोग अनुशंसित नहीं है क्योंकि इसका परिणाम क्रमबद्ध सरणी में नहीं होता है। इसे भविष्य के संदर्भ के लिए यहां छोड़ा जा रहा है, क्योंकि यह विचार दुर्लभ नहीं है।
objs.sort(function(a,b){return b.last_nom>a.last_nom})
भ्रम से बचने के लिए आपको उन्हें निचले मामले में बदलने की आवश्यकता हो सकती है।
objs.sort(function (a,b) {
var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase()
if (nameA < nameB)
return -1;
if (nameA > nameB)
return 1;
return 0; //no sorting
})
function compare(propName) {
return function(a,b) {
if (a[propName] < b[propName])
return -1;
if (a[propName] > b[propName])
return 1;
return 0;
};
}
objs.sort(compare("last_nom"));
मूल उदाहरण को देखते हुए:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
कई क्षेत्रों के आधार पर छाँटें:
objs.sort(function(left, right) {
var last_nom_order = left.last_nom.localeCompare(right.last_nom);
var first_nom_order = left.first_nom.localeCompare(right.first_nom);
return last_nom_order || first_nom_order;
});
टिप्पणियाँ
a.localeCompare(b)
सार्वभौमिक रूप से समर्थित है और यदिa<b
है तो -1,0,1 लौटाता है ,a==b
,a>b
क्रमशः।- अंतिम पंक्ति में
||
last_nom
कोfirst_nom
से अधिक प्राथमिकता देता है। - अंकीय क्षेत्रों पर घटाव कार्य करता है:
var age_order = left.age - right.age;
- रिवर्स ऑर्डर के लिए नकारात्मक,
return -last_nom_order || -first_nom_order || -age_order;
यह एक साधारण समस्या है, पता नहीं लोगों के पास इतना जटिल समाधान क्यों है।
एक साधारण सॉर्ट फ़ंक्शन (त्वरित-क्रमबद्ध एल्गोरिथम पर आधारित):
function sortObjectsArray(objectsArray, sortKey)
{
// Quick Sort:
var retVal;
if (1 < objectsArray.length)
{
var pivotIndex = Math.floor((objectsArray.length - 1) / 2); // middle index
var pivotItem = objectsArray[pivotIndex]; // value in the middle index
var less = [], more = [];
objectsArray.splice(pivotIndex, 1); // remove the item in the pivot position
objectsArray.forEach(function(value, index, array)
{
value[sortKey] <= pivotItem[sortKey] ? // compare the 'sortKey' proiperty
less.push(value) :
more.push(value) ;
});
retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
}
else
{
retVal = objectsArray;
}
return retVal;
}
उदाहरण का प्रयोग करें:
var myArr =
[
{ val: 'x', idx: 3 },
{ val: 'y', idx: 2 },
{ val: 'z', idx: 5 },
];
myArr = sortObjectsArray(myArr, 'idx');
रामदा का उपयोग करना,
npm ramda इंस्टॉल करें
import R from 'ramda'
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)
मैंने अभी-अभी Ege zcan के डायनामिक सॉर्ट को ऑब्जेक्ट के अंदर गहराई में जाने के लिए बढ़ाया है। यदि डेटा इस तरह दिखता है:
obj = [
{
a: { a: 1, b: 2, c: 3 },
b: { a: 4, b: 5, c: 6 }
},
{
a: { a: 3, b: 2, c: 1 },
b: { a: 6, b: 5, c: 4 }
}];
और यदि आप इसे a.a संपत्ति पर क्रमबद्ध करना चाहते हैं तो मुझे लगता है कि मेरी वृद्धि बहुत अच्छी तरह से मदद करती है। मैं इस तरह की वस्तुओं में नई कार्यक्षमता जोड़ता हूं:
Object.defineProperty(Object.prototype, 'deepVal', {
enumerable: false,
writable: true,
value: function (propertyChain) {
var levels = propertyChain.split('.');
parent = this;
for (var i = 0; i < levels.length; i++) {
if (!parent[levels[i]])
return undefined;
parent = parent[levels[i]];
}
return parent;
}
});
और _dynamicSort के वापसी फ़ंक्शन को बदल दिया:
return function (a,b) {
var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
return result * sortOrder;
}
और अब आप a.a. के अनुसार इस प्रकार क्रमित कर सकते हैं:
obj.sortBy('a.a');
JSFiddle में पूरी स्क्रिप्ट देखें
ये कोशिश करें,
UPTO ES5
//Ascending Sort
items.sort(function (a, b) {
return a.value - b.value;
});
//Descending Sort
items.sort(function (a, b) {
return b.value - a.value;
});
IN ES6 & above:
// Ascending sort
items.sort((a, b) => a.value - b.value);
// Descending Sort
items.sort((a, b) => b.value - a.value);
आप पुन: प्रयोज्य सॉर्ट फ़ंक्शन का उपयोग कर सकते हैं।
Array.prototype.order = function (prop, methods = {}) {
if (prop?.constructor == Object) {
methods = prop;
prop = null;
}
const [orderType_a, orderType_b] = methods.reverse ? [1, -1] : [-1, 1];
const $ = x => prop
? methods.insensitive
? String(x[prop]).toLowerCase()
: x[prop]
: methods.insensitive
? String(x).toLowerCase()
: x;
const fn = (a, b) => $(a) < $(b) ? orderType_a : $(b) < $(a) ? orderType_b : 0;
return this.sort(fn);
};
इसका उपयोग सरणी और ऑब्जेक्ट दोनों को सरणी
में सॉर्ट करने के लिए किया जा सकता है।
let items = [{ x: "Z" }, 3, "1", "0", 2, { x: "a" }, { x: 0 }];
items
.order("x", { insensitive: 1 })
// [ { x: 0 }, { x: 'a' }, 3, '1', '0', 2, { x: 'Z' } ]
.order({ reverse: 1 })
// [ { x: 0 }, { x: 'a' }, 3, 2, { x: 'Z' }, '1', '0' ]
.sort(x => typeof x == "string" || typeof x == "number" ? -1 : 0)
// [ '0', '1', 2, 3, { x: 0 }, { x: 'a' }, { x: 'Z' } ]
पहला (वैकल्पिक) > सरणी में समाहित ऑब्जेक्ट को सॉर्ट करने के लिए।
दूसरा तरीका है > { reverse: any, insensitive: any }
आप शॉर्ट कोड क्यों नहीं लिखते?
objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)
1, -1, 0
a>b && 1|| -1
a> b ? 1 : -1
के बराबर है, ऑपरेटर &&
पहले तार्किक false
मान देता है, ऑपरेटर ||
पहले तार्किक देता है true
मूल्य।
objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)