etc./StackOverFlow

문자열 속성 값으로 객체 배열 정렬

청렴결백한 만능 재주꾼 2021. 10. 7. 22:03
반응형

질문자 :Tyrone Slothrop


JavaScript 객체 배열이 있습니다.

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ];

JavaScript에서 last_nom 값을 기준으로 정렬하려면 어떻게 해야 합니까?

sort(a,b) 에 대해 알고 있지만 문자열과 숫자에서만 작동하는 것 같습니다. 내 객체에 toString() 메서드를 추가해야 합니까?



자신만의 비교 함수를 작성하는 것은 쉽습니다.

 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))

Wogan

전달한 값으로 개체를 정렬하는 동적 정렬 함수를 만들 수도 있습니다.

 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");

Ege Özcan

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) });

Vlad Bezden

밑줄.js

밑줄 사용, 작고 멋진...

sortBy_.sortBy(list, iterator, [context]) iterator를 통해 각 값을 실행한 결과에 따라 오름차순으로 순위가 매겨진 목록의 정렬된 복사본을 반환합니다. Iterator는 정렬 기준으로 사용할 속성의 문자열 이름(예: 길이)일 수도 있습니다.

 var objs = [ { first_nom: 'Lazslo',last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; var sortedObjs = _.sortBy( objs, 'first_nom' );

David Morrow

성이 중복되는 경우 이름별로 정렬할 수 있습니다.

 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; });

kennebec

프로토타입 상속을 사용하여 이 문제에 대한 간단하고 빠른 솔루션:

 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"}]

업데이트: 더 이상 원래 배열을 수정하지 않습니다.


Vinay Aggarwal

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; });

0leg

올바르지 않은 오래된 답변:

 arr.sort((a, b) => a.name > b.name)

업데이트

Beauchamp의 의견에서 :

 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()true1 , false0 합니다.


Damjan Pavlica

Lodash.js (Underscore.js의 상위 집합)

모든 간단한 로직에 프레임워크를 추가하지 않는 것이 좋지만 잘 테스트된 유틸리티 프레임워크에 의존하면 개발 속도를 높이고 버그의 양을 줄일 수 있습니다.

Lodash는 매우 깨끗한 코드를 생성하고 보다 기능적인 프로그래밍 스타일을 촉진합니다. 코드의 의도가 무엇인지 한눈에 알 수 있습니다.

OP의 문제는 다음과 같이 간단히 해결할 수 있습니다.

 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 를 사용하여 일치해야 하는 속성의 경로를 지정할 수 있습니다. 중첩된 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);

Nico Van Belle

이 특정 접근 방식이 제안된 것을 본 적이 없으므로 다음은 stringnumber 유형 모두에 사용할 수 있는 간결한 비교 방법입니다.

 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( || ) 이 JavaScript에서 작동하는 방식 때문에 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;

덧붙여서, 이것을 다른 언어 에서는 3방향 비교 "우주선"( <=> ) 연산자라고 합니다.

마지막으로 화살표 기능을 사용하지 않는 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));


Patrick Roberts

가장 쉬운 방법: Lodash를 사용할 수 있습니다.

( https://lodash.com/docs/4.17.10#orderBy )

이 메서드는 _.sortBy 와 비슷하지만 정렬 기준이 되는 반복자의 정렬 순서를 지정할 수 있다는 점을 제외하고는 다릅니다. order를 지정하지 않으면 모든 값이 오름차순으로 정렬됩니다. 그렇지 않으면 해당 값의 내림차순 정렬에 대해 "desc" 순서를 지정하거나 해당 값의 오름차순 정렬 순서에 대해 "asc" 순서를 지정합니다.

인수

컬렉션(Array|Object): 반복할 컬렉션입니다. [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): 정렬 기준이 되는 반복 항목입니다. [orders] (string[]): iteratees의 정렬 순서.

보고

(배열): 새로 정렬된 배열을 반환합니다.


 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']);

Harshal Y.

사용자 정의 비교 함수를 사용하는 대신 사용자 정의 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();

Christoph

여기에는 많은 좋은 답변이 있지만 훨씬 더 복잡한 정렬을 달성하기 위해 매우 간단하게 확장할 수 있다는 점을 지적하고 싶습니다. 당신이 해야 할 유일한 것은 다음과 같은 비교 함수를 연결하기 위해 OR 연산자를 사용하는 것입니다:

 objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

여기서 fn1 , fn2 , ...는 [-1,0,1]을 반환하는 정렬 함수입니다. 이것은 SQL의 ORDER BY와 거의 같은 "fn1에 의한 정렬", "fn2에 의한 정렬"의 결과입니다.

이 솔루션은 || true 로 변환될 수 있는 첫 번째 평가된 표현식으로 평가되는 연산자입니다.

가장 간단한 형식 에는 다음과 같은 인라인 함수가 하나만 있습니다.

 // 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") )

여기서 요점은 기능적 접근 방식의 순수 JavaScript가 외부 라이브러리나 복잡한 코드 없이도 먼 길을 갈 수 있다는 것입니다. 또한 문자열 구문 분석을 수행할 필요가 없기 때문에 매우 효과적입니다.


Tero Tolonen

사용 예:

 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; }; };

Jamie Mason

이 시도,

 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);

Abhishek

이 질문이 너무 오래되었다는 것을 알고 있지만 나와 유사한 구현을 보지 못했습니다.
이 버전은 Schwartzian 변환 관용구를 기반으로 합니다.

 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'));

a8m

대소문자 구분

 arr.sort((a, b) => a.name > b.name ? 1 : -1);

대소문자를 구분하지 않음

 arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

메모

순서가 변경되지 않으면(같은 문자열의 경우) 조건 > 이 실패하고 -1 이 반환됩니다. 그러나 문자열이 동일한 경우 1 또는 -1을 반환하면 올바른 출력이 됩니다.

다른 옵션을 사용할 수 >= 대신 연산자 >


muasif80

(더) 복잡한 객체 배열 정렬하기

이 배열과 같은 더 복잡한 데이터 구조를 접할 수 있으므로 솔루션을 확장하겠습니다.

TL;DR

@ege-Özcan 의 매우 멋진 답변을 기반으로 하는 더 많은 플러그형 버전입니다.

문제

아래에 발생하여 변경할 수 없습니다. 또한 일시적으로 개체를 평평하게 만들고 싶지 않았습니다. 또한 주로 성능상의 이유와 직접 구현하는 재미를 위해 밑줄 / lodash를 사용하고 싶지 않았습니다.

 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에 대한 작업 예제


eljefedelrodeodeljefe

또 하나의 옵션:

 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));

기본적으로 오름차순으로 정렬합니다.


ravshansbox

간단한 방법:

 objs.sort(function(a,b) { return b.last_nom.toLowerCase() < a.last_nom.toLowerCase(); });

문자열을 비교할 때 오류를 방지하려면 '.toLowerCase()'


Caio Ladislau

속성별로 객체 배열을 정렬하는 간단한 함수

 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

Francois Girard

경고!
이 솔루션을 사용하면 정렬된 배열 이 생성되지 않으므로 사용하지 않는 것이 좋습니다. 아이디어가 드물지 않기 때문에 향후 참조를 위해 여기에 남겨둡니다.

 objs.sort(function(a,b){return b.last_nom>a.last_nom})

Roshni Bokade

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; } }

Behnam Shomali

Ege의 동적 솔루션과 Vinay의 아이디어를 결합하면 다음과 같은 강력한 솔루션을 얻을 수 있습니다.

 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");

Mike R

이것은 이것에 대한 나의 견해입니다.

order 매개변수는 선택 사항이며 오름차순의 경우 기본값은 "ASC"입니다.

악센트가 있는 문자에서 작동하며 대소문자를 구분하지 않습니다 .

참고: ORIGINAL 배열을 정렬하고 반환합니다.

 function sanitizeToSort(str) { return str .normalize('NFD') // REMOVE ACCENTED AND DIACRITICS .replace(/[\u0300-\u036f]/g,'') // REMOVE ACCENTED AND DIACRITICS .toLowerCase() // SORT WILL BE CASE INSENSITIVE ; } function sortByProperty(arr, property, order="ASC") { arr.forEach((item) => item.tempProp = sanitizeToSort(item[property])); arr.sort((a,b) => order === "ASC" ? a.tempProp > b.tempProp ? 1 : a.tempProp < b.tempProp ? -1 : 0 : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ? 1 : 0 ); arr.forEach((item) => delete item.tempProp); return arr; }

단편

 function sanitizeToSort(str) { return str .normalize('NFD') // REMOVE ACCENTED CHARS .replace(/[\u0300-\u036f]/g,'') // REMOVE DIACRITICS .toLowerCase() ; } function sortByProperty(arr, property, order="ASC") { arr.forEach((item) => item.tempProp = sanitizeToSort(item[property])); arr.sort((a,b) => order === "ASC" ? a.tempProp > b.tempProp ? 1 : a.tempProp < b.tempProp ? -1 : 0 : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ? 1 : 0 ); arr.forEach((item) => delete item.tempProp); return arr; } const rockStars = [ { name: "Axl", lastname: "Rose" }, { name: "Elthon", lastname: "John" }, { name: "Paul", lastname: "McCartney" }, { name: "Lou", lastname: "Reed" }, { name: "freddie", // WORKS ON LOWER/UPPER CASE lastname: "mercury" }, { name: "Ámy", // WORKS ON ACCENTED CHARS TOO lastname: "winehouse"} ]; sortByProperty(rockStars,"name"); console.log("Ordered by name AZ:"); rockStars.forEach((item) => console.log(item.name + " " + item.lastname)); sortByProperty(rockStars,"lastname","DESC"); console.log("\nOrdered by lastname ZA:"); rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));


cbdeveloper

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"));

Evgenii

왜 짧은 코드를 작성하지 않습니까?

 objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)

artem

귀하의 예에 따르면 하나가 아닌 두 개의 필드(성, 이름)를 기준으로 정렬해야 합니다. Alasql 라이브러리를 사용하여 이 정렬을 한 줄로 만들 수 있습니다.

 var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

jsFiddle 에서 이 예제를 시도하십시오.


agershun

람다를 사용하여,

npm 람다 설치

 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)

Sridhar Sg

원래 예를 보면 다음과 같습니다.

 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 , a==b , a>b 각각 -1,0,1을 반환합니다.
  • || 마지막 줄에서는 last_nom 우선 순위가 first_nom .
  • 빼기는 숫자 필드에서 작동합니다. var age_order = left.age - right.age;
  • 역순으로 부정하고 return -last_nom_order || -first_nom_order || -age_order;

Bob Stein

출처 : http:www.stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value

반응형