날짜 값이있는 단일 키로 객체 배열 정렬


257

여러 키 값 쌍이있는 객체 배열이 있으며 'updated_at'에 따라 정렬해야합니다.

[
    {
        "updated_at" : "2012-01-01T06:25:24Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-09T11:25:13Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-05T04:13:24Z",
        "foo" : "bar"
    }
]

가장 효율적인 방법은 무엇입니까?


@Topener이 링크는 PHP에 관한 질문 인 것 같습니다
David Brainer

내 실수 .. 제대로 읽지 않았다
르네 냄비

답변:


338

사용할 수 있습니다 Array.sort.

예를 들면 다음과 같습니다.

var arr = [{
    "updated_at": "2012-01-01T06:25:24Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-09T11:25:13Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-05T04:13:24Z",
    "foo": "bar"
  }
]

arr.sort(function(a, b) {
  var keyA = new Date(a.updated_at),
    keyB = new Date(b.updated_at);
  // Compare the 2 dates
  if (keyA < keyB) return -1;
  if (keyA > keyB) return 1;
  return 0;
});

console.log(arr);


17
당신은 keyA - keyB(또는 가능 keyB - keyA) 을 사용할 수 없습니까? 날짜 객체에는 valueOf()메소드가 있습니다.
soktinpk

반품 updated_at <b. updated_at? 1 : -1이 저에게 효과적입니다. 날짜 형식으로 구문 분석 할 필요가 없습니다.
oliversisson

a-b긴 코드를 피 하려면 그냥 할 수있는 기능 이 정말 중요합니다. 이 경우 긴 코드가 반드시 나쁘지는 않지만 자세한 내용으로 인해 이해하기가 더 어렵다고 생각합니다. 나는 현재 사용하고 있습니다 values.sort((a,b)=>a.attr-b.attr). 배열을 정렬해야 할 때마다 5 줄을 써야하는 것은 지루합니다.
AnnanFay

이 예제는 효과적이지 않으며 많은 불필요한 계산을 수행합니다. 정렬은 유효한 결과로 양수 또는 음수를 취할 수 있습니다. 1,0,1로 강제하는 추가 계산은 필요하지 않으며 단순히 실행 당 추가 계산을 추가합니다.
Patrick W. McMahon

위대한 thjank you 작동
Andy

158

나는 이미 비슷한 질문에 대답했다 : 객체 배열을 정렬하는 간단한 함수

그 질문에 대해 나는 당신이 원하는 것을 할 수있는이 작은 기능을 만들었습니다.

function sortByKey(array, key) {
    return array.sort(function(a, b) {
        var x = a[key]; var y = b[key];
        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
}

11
당신은 선생님입니다. blogs.citypages.com/blotter/assets_c/2009/02/…
Dom

2
이것을 어떻게 바꾸시겠습니까?

4
대소 문자를 구분하지 않기 위해 x와 y 변수에 .toLowerCase ()를 추가 할 수 있습니다.
Jacob van Lingen

4
이와 같은 분류 기능에 의해 단지 곱셈 결과를 역으로 -1:)
Svish

5
또는 출력을 가져 와서 array = array.reverse()기능을 사용하십시오 .
Luke Stevenson

31

에 Array.sort () 메소드 대신 배열의 요소를 정렬하고 배열을 반환한다. Immutable 이 아니기 때문에 Array.sort ()에 주의하십시오 . 불변 정렬의 경우 immutable-sort를 사용하십시오 .

이 방법은 현재 updated_atISO 형식으로 배열을 정렬하는 것 입니다. new Data(iso_string).getTime()ISO 시간을 Unix 타임 스탬프로 변환 하는 데 사용 합니다. 유닉스 타임 스탬프는 간단한 수학을 할 수있는 숫자입니다. 결과의 첫 번째 및 두 번째 타임 스탬프를 뺍니다. 첫 번째 타임 스탬프가 두 번째 타임 스탬프보다 크면 반환 숫자는 양수입니다. 두 번째 숫자가 첫 번째 숫자보다 크면 반환 값은 음수입니다. 둘이 동일하면 리턴은 0이됩니다. 인라인 함수에 필요한 반환 값으로 완벽하게 정렬됩니다.

대한 ES6 :

arr.sort((a,b) => new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime());

대한 ES5 :

arr.sort(function(a,b){ 
 return new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime();
});

updated_at유닉스 타임 스탬프로 변경하면 다음과 같이 할 수 있습니다.

대한 ES6 :

arr.sort((a,b) => a.updated_at - b.updated_at);

대한 ES5 :

arr.sort(function(a,b){ 
 return a.updated_at - b.updated_at;
});

이 글을 쓰는 시점에서 최신 브라우저는 ES6를 지원하지 않습니다. 최신 브라우저에서 ES6을 사용하려면 babel 을 사용 하여 코드를 ES5로 변환하십시오. 가까운 시일 내에 ES6에 대한 브라우저 지원이 예상됩니다.

Array.sort () 는 가능한 세 가지 결과 중 하나의 반환 값을 받아야합니다.

  • 양수 (첫 번째 항목> 두 번째 항목)
  • 음수 (첫 번째 항목 <두 번째 항목)
  • 두 항목이 같으면 0

인라인 함수의 리턴 값은 양수 또는 음수 일 수 있습니다. Array.Sort ()는 반환 번호가 무엇인지 신경 쓰지 않습니다. 반환 값이 양수, 음수 또는 0인지에만 관심이 있습니다.

불변 정렬의 경우 : (ES6의 예)

const sort = require('immutable-sort');
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);

다음과 같이 작성할 수도 있습니다.

import sort from 'immutable-sort';
const array = [1, 5, 2, 4, 3];
const sortedArray = sort(array);

가져 오기-가져 오기는 ES6에 자바 스크립트를 포함하는 새로운 방법이며 코드를 매우 깨끗하게 보이게합니다. 내 개인적인 마음에 드는 것.

불변 정렬은 소스 배열을 변경하지 않고 새로운 배열을 반환합니다. const불변 데이터에는 사용 을 권장합니다.


19

@David Brainer-Bankers의 대답 은 약간 알파벳순으로 문자열 또는 숫자 순으로 정렬되어 있으며 대문자로 시작하는 단어가 소문자로 시작하는 단어 (예 : "apple, Early")로 정렬되지 않도록합니다. 순서대로 표시됩니다.

function sortByKey(array, key) {
    return array.sort(function(a, b) {
        var x = a[key];
        var y = b[key];

        if (typeof x == "string")
        {
            x = (""+x).toLowerCase(); 
        }
        if (typeof y == "string")
        {
            y = (""+y).toLowerCase();
        }

        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });
}

3
a [key]와 b [key]가 모두 문자열이 아닌 경우 제안 된 솔루션에서 오류가 발생할 수 있습니다. 나는 Y는 Y와 y.toLowerCase () = ( ""+ Y) = .toLowerCase를 교체하는 것이 좋습니다 ()
user8074

sort는 양수 또는 음수를 유효한 반환 값으로 사용할 수 있습니다. 1,0,1로 강제 계산하기 위해 추가 계산이 필요하지 않습니다. 간단한 반환 값을 복잡하게 만듭니다. 아무것도하지 않는 추가 계산을 추가하지 않는 것이 가장 좋습니다.
Patrick W. McMahon


6

ES2015 지원을 통해 다음을 수행 할 수 있습니다.

foo.sort((a, b) => a.updated_at < b.updated_at ? -1 : 1)

1
<를-로 바꾸고 '를 제거하면 인라인이 필요하지 않습니까? -1 : 1 "유효한 반품을받습니다.이 예는 같거나 예상치 못한 결과를 줄 수있는 항목을 이동시킵니다. 동일한 항목에 대해 0을 반환해야합니다.
Patrick W. McMahon

설명해 주셔서 감사합니다
knowbody

updated_at이 ISO 시간이면 작동하지 않습니다. 이 예에서는 Unix 타임 스탬프가 있지만 OP는 ISO 형식의 데이터를 게시했다고 가정합니다. 따라서 비교를 수행하려면 유닉스 타임 스탬프로 변환해야합니다. 이 작업을 수행 new Date(iso_str).getTime()하면 Unix 타임 스탬프가 반환됩니다.
Patrick W. McMahon

5

가져온 데이터

[
    {
        "gameStatus": "1",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 11:32:04"
    },
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:08:24"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:35:40"
    },
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 10:42:53"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 10:54:09"
    },
    {
        "gameStatus": "0",
        "userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
        "created_at": "2018-12-19 18:46:22"
    },
    {
        "gameStatus": "1",
        "userId": "7118ed61-d8d9-4098-a81b-484158806d21",
        "created_at": "2018-12-20 10:50:48"
    }
]

오름차순

arr.sort(function(a, b){
    var keyA = new Date(a.updated_at),
        keyB = new Date(b.updated_at);
    // Compare the 2 dates
    if(keyA < keyB) return -1;
    if(keyA > keyB) return 1;
    return 0;
});

Asc 주문 예

[
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 10:42:53"
    },
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:08:24"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:35:40"
    },
    {
        "gameStatus": "0",
        "userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
        "created_at": "2018-12-19 18:46:22"
    },
    {
        "gameStatus": "1",
        "userId": "7118ed61-d8d9-4098-a81b-484158806d21",
        "created_at": "2018-12-20 10:50:48"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 10:54:09"
    },
    {
        "gameStatus": "1",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 11:32:04"
    }
]

내림차순

arr.sort(function(a, b){
    var keyA = new Date(a.updated_at),
        keyB = new Date(b.updated_at);
    // Compare the 2 dates
    if(keyA > keyB) return -1;
    if(keyA < keyB) return 1;
    return 0;
});

설명 순서의 예

[
    {
        "gameStatus": "1",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 11:32:04"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-20 10:54:09"
    },
    {
        "gameStatus": "1",
        "userId": "7118ed61-d8d9-4098-a81b-484158806d21",
        "created_at": "2018-12-20 10:50:48"
    },
    {
        "gameStatus": "0",
        "userId": "1a2fefb0-5ae2-47eb-82ff-d1b2cc27875a",
        "created_at": "2018-12-19 18:46:22"
    },
    {
        "gameStatus": "2",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:35:40"
    },
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 18:08:24"
    },
    {
        "gameStatus": "0",
        "userId": "c02cfb18-ae66-430b-9524-67d9dd8f6a50",
        "created_at": "2018-12-19 10:42:53"
    }
]

3

으로 대답의 상태, 당신은 사용할 수 있습니다 Array.sort.

arr.sort(function(a,b){return new Date(a.updated_at) - new Date(b.updated_at)})

arr = [
    {
        "updated_at" : "2012-01-01T06:25:24Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-09T11:25:13Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-05T04:13:24Z",
        "foo" : "bar"
    }
];
arr.sort(function(a,b){return new Date(a.updated_at) - new Date(b.updated_at)});
console.log(arr);


2

똑같은 일을하지만 더 짧은 다른 수학적인 방법 :

arr.sort(function(a, b){
    var diff = new Date(a.updated_at) - new Date(b.updated_at);
    return diff/(Math.abs(diff)||1);
});

또는 매끄러운 람다 화살표 스타일로 :

arr.sort((a, b) => {
    var diff = new Date(a.updated_at) - new Date(b.updated_at);
    return diff/(Math.abs(diff)||1);
});

이 방법은 모든 숫자 입력으로 수행 할 수 있습니다


과소 답변
two7s_clash


2

Typescript에서 객체 배열에서 문자열, 날짜 및 숫자를 검색하는 데 사용할 수있는 정렬 기능을 만들었습니다. 여러 필드를 기준으로 정렬 할 수도 있습니다.

export type SortType = 'string' | 'number' | 'date';
export type SortingOrder = 'asc' | 'desc';

export interface SortOptions {
  sortByKey: string;
  sortType?: SortType;
  sortingOrder?: SortingOrder;
}


class CustomSorting {
    static sortArrayOfObjects(fields: SortOptions[] = [{sortByKey: 'value', sortType: 'string', sortingOrder: 'desc'}]) {
        return (a, b) => fields
          .map((field) => {
            if (!a[field.sortByKey] || !b[field.sortByKey]) {
              return 0;
            }

            const direction = field.sortingOrder === 'asc' ? 1 : -1;

            let firstValue;
            let secondValue;

            if (field.sortType === 'string') {
              firstValue = a[field.sortByKey].toUpperCase();
              secondValue = b[field.sortByKey].toUpperCase();
            } else if (field.sortType === 'number') {
              firstValue = parseInt(a[field.sortByKey], 10);
              secondValue = parseInt(b[field.sortByKey], 10);
            } else if (field.sortType === 'date') {
              firstValue = new Date(a[field.sortByKey]);
              secondValue = new Date(b[field.sortByKey]);
            }
            return firstValue > secondValue ? direction : firstValue < secondValue ? -(direction) : 0;

          })
          .reduce((pos, neg) => pos ? pos : neg, 0);
      }
    }
}

용법:

const sortOptions = [{
      sortByKey: 'anyKey',
      sortType: 'string',
      sortingOrder: 'asc',
    }];

arrayOfObjects.sort(CustomSorting.sortArrayOfObjects(sortOptions));

1

클라이언트를 최신 브라우저로 제한하지 않는 한 ISO 형식의 날짜를 기준으로 정렬하면 비용이 많이들 수 있습니다. 이렇게하면 문자열을 구문 분석하여 정확한 타임 스탬프를 만들 수 있습니다.

입력 이 확실 하고 입력 이 항상 yyyy-mm-ddThh : mm : ss 및 GMT (Z) 라는 것을 알고 있다면 각 멤버에서 숫자를 추출하고 정수처럼 비교할 수 있습니다

array.sort(function(a,b){
    return a.updated_at.replace(/\D+/g,'')-b.updated_at.replace(/\D+/g,'');
});

날짜가 다르게 형식화 될 수 있다면 iso에 도전하는 사람들을 위해 무언가를 추가해야 할 수도 있습니다.

Date.fromISO: function(s){
    var day, tz,
    rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
    p= rx.exec(s) || [];
    if(p[1]){
        day= p[1].split(/\D/).map(function(itm){
            return parseInt(itm, 10) || 0;
        });
        day[1]-= 1;
        day= new Date(Date.UTC.apply(Date, day));
        if(!day.getDate()) return NaN;
        if(p[5]){
            tz= (parseInt(p[5], 10)*60);
            if(p[6]) tz+= parseInt(p[6], 10);
            if(p[4]== '+') tz*= -1;
            if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
        }
        return day;
    }
    return NaN;
}
if(!Array.prototype.map){
    Array.prototype.map= function(fun, scope){
        var T= this, L= T.length, A= Array(L), i= 0;
        if(typeof fun== 'function'){
            while(i< L){
                if(i in T){
                    A[i]= fun.call(scope, T[i], i, T);
                }
                ++i;
            }
            return A;
        }
    }
}
}

2
그냥 사용할 수 Date.parse없습니까?
로켓 Hazmat

1

완전성을 위해 sortBy의 가능한 짧은 일반 구현이 있습니다.

function sortBy(list, keyFunc) {
  return list.sort((a,b) => keyFunc(a) - keyFunc(b));
}

sortBy([{"key": 2}, {"key": 1}], o => o["key"])

이것은 정렬하는 배열 정렬 방법을 사용합니다. 사본의 경우 arr.concat () 또는 arr.slice (0) 또는 유사한 메소드를 사용하여 사본을 작성할 수 있습니다.


1

이를 통해 정렬에 사용할 핵심 기능을 전달할 수 있습니다

Array.prototype.sortBy = function(key_func, reverse=false){
    return this.sort( (a, b) => {
        var keyA = key_func(a),
            keyB = key_func(b);
        if(keyA < keyB) return reverse? 1: -1;
        if(keyA > keyB) return reverse? -1: 1;
        return 0;
    }); 
}

예를 들어

var arr = [ {date: "01/12/00", balls: {red: "a8",  blue: 10}},
            {date: "12/13/05", balls: {red: "d6" , blue: 11}},
            {date: "03/02/04", balls: {red: "c4" , blue: 15}} ]

우린 할 수있어

arr.sortBy(el => el.balls.red)
/* would result in
[ {date: "01/12/00", balls: {red: "a8", blue: 10}},
  {date: "03/02/04", balls: {red: "c4", blue: 15}},
  {date: "12/13/05", balls: {red: "d6", blue: 11}} ]
*/

또는

arr.sortBy(el => new Date(el.date), true)   // second argument to reverse it
/* would result in
[ {date: "12/13/05", balls: {red: "d6", blue:11}},
  {date: "03/02/04", balls: {red: "c4", blue:15}},
  {date: "01/12/00", balls: {red: "a8", blue:10}} ]
*/

또는

arr.sortBy(el => el.balls.blue + parseInt(el.balls.red[1]))
/* would result in
[ {date: "12/13/05", balls: {red: "d6", blue:11}},    // red + blue= 17
  {date: "01/12/00", balls: {red: "a8", blue:10}},    // red + blue= 18
  {date: "03/02/04", balls: {red: "c4", blue:15}} ]   // red + blue= 19
*/

1

Lodash 유틸리티 라이브러리를 사용 하여이 문제를 해결할 수 있습니다 (매우 효율적인 라이브러리입니다).

const data = [{
    "updated_at": "2012-01-01T06:25:24Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-09T11:25:13Z",
    "foo": "bar"
  },
  {
    "updated_at": "2012-01-05T04:13:24Z",
    "foo": "bar"
  }
]

const ordered = _.orderBy(
  data,
  function(item) {
    return item.updated_at;
  }
);

console.log(ordered)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

https://lodash.com/docs/4.17.15#orderBy에서 설명서를 찾을 수 있습니다.


0

클로저를 만들어 여기에 전달하면 내 예제가 작동합니다.

$.get('https://data.seattle.gov/resource/3k2p-39jp.json?$limit=10&$where=within_circle(incident_location, 47.594972, -122.331518, 1609.34)', 
  function(responce) {

    var filter = 'event_clearance_group', //sort by key group name
    data = responce; 

    var compare = function (filter) {
        return function (a,b) {
            var a = a[filter],
                b = b[filter];

            if (a < b) {
                return -1;
            } else if (a > b) {
                return 1;
            } else {
                return 0;
            }
        };
    };

    filter = compare(filter); //set filter

    console.log(data.sort(filter));
});

0
var months = [
    {
        "updated_at" : "2012-01-01T06:25:24Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-09T11:25:13Z",
        "foo" : "bar"
    },
    {
        "updated_at" : "2012-01-05T04:13:24Z",
        "foo" : "bar"
    }];
months.sort((a, b)=>{
    var keyA = new Date(a.updated_at),
        keyB = new Date(b.updated_at);
    // Compare the 2 dates
    if(keyA < keyB) return -1;
    if(keyA > keyB) return 1;
    return 0;
});
console.log(months);

0
  • Array.sort()배열을 정렬하는 데 사용
  • 스프레드 연산자 ( )를 사용하여 배열을 복제 하여 함수를 순수하게 만들기
  • 원하는 키 ( updated_at)로 정렬
  • 날짜 문자열을 날짜 객체로 변환
  • Array.sort() 부정맥 연산을 수행 할 수있는 숫자 / 대상인 경우 현재 및 다음 항목에서 두 속성을 빼서 작동
const input = [
  {
    updated_at: '2012-01-01T06:25:24Z',
    foo: 'bar',
  },
  {
    updated_at: '2012-01-09T11:25:13Z',
    foo: 'bar',
  },
  {
    updated_at: '2012-01-05T04:13:24Z',
    foo: 'bar',
  }
];

const sortByUpdatedAt = (items) => [...items].sort((itemA, itemB) => new Date(itemA.updated_at) - new Date(itemB.updated_at));

const output = sortByUpdatedAt(input);

console.log(input);
/*
[ { updated_at: '2012-01-01T06:25:24Z', foo: 'bar' }, 
  { updated_at: '2012-01-09T11:25:13Z', foo: 'bar' }, 
  { updated_at: '2012-01-05T04:13:24Z', foo: 'bar' } ]
*/
console.log(output)
/*
[ { updated_at: '2012-01-01T06:25:24Z', foo: 'bar' }, 
  { updated_at: '2012-01-05T04:13:24Z', foo: 'bar' }, 
  { updated_at: '2012-01-09T11:25:13Z', foo: 'bar' } ]
*/

0

나는 똑같은 문제에 직면하여 일반적인 이유로 이것을 처리하고 이것을 위해 함수를 작성합니다.

//example:
//array: [{name: 'idan', workerType: '3'}, {name: 'stas', workerType: '5'}, {name: 'kirill', workerType: '2'}]
//keyField: 'workerType'
// keysArray: ['4', '3', '2', '5', '6']
sortByArrayOfKeys = (array, keyField, keysArray) => {
    array.sort((a, b) => {
        const aIndex = keysArray.indexOf(a[keyField])
        const bIndex = keysArray.indexOf(b[keyField])
        if (aIndex < bIndex) return -1;
        if (aIndex > bIndex) return 1;
        return 0;
    })
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.