2012-01-12 54 views
143

Tôi có một mảng các đối tượng với một số cặp giá trị quan trọng, và tôi cần phải sắp xếp chúng dựa trên 'updated_at':Sắp xếp mảng các đối tượng bằng cách chìa khóa duy nhất với giá trị ngày

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

gì là cách hiệu quả nhất để làm như vậy?

+0

chức năng tùy chỉnh: http://stackoverflow.com/questions/777597/sorting-an-associative-array-in-php –

+0

@Topener liên kết đó trông giống như nó là một câu hỏi về PHP –

+0

sai lầm của tôi .. đã không đọc nó một cách chính xác –

Trả lời

207

Bạn có thể sử dụng Array.sort.

Dưới đây là một (chưa được kiểm tra) ví dụ:

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

Bạn không thể sử dụng 'keyA - keyB' (hoặc có thể' keyB - keyA')? Các đối tượng ngày tháng có một phương thức 'valueOf()'. – soktinpk

+0

@soktinpk: Vâng. Cần làm việc. –

+0

var keyA = new Date (a.updated_at), Lưu ý là ',' nó phải được thay thế bởi ";". Khác khôn ngoan nó sẽ ném một lỗi – brk

121

tôi đã trả lời một câu hỏi thực sự tương tự ở đây: Simple function to sort an array of objects

Đối với câu hỏi mà tôi tạo ra chức năng này nhỏ có thể làm những gì bạn muốn:

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

Bạn, thưa bạn, là người đàn ông. http://blogs.citypages.com/blotter/assets_c/2009/02/YouDaManJesus-thumb-500x435.jpg – Dom

+2

Bạn sẽ đảo ngược điều này như thế nào? –

+3

Để làm cho nó không phân biệt dạng chữ, bạn có thể thêm. ToLowerCase() vào biến x và y –

1

Phân loại theo một tiêu chuẩn ISO định dạng ngày có thể tốn kém, trừ khi bạn giới hạn các khách hàng để các trình duyệt mới nhất và tốt nhất, có thể tạo ra các dấu thời gian đúng theo Ngày phân tích cú pháp chuỗi.

Nếu bạn là chắc chắn của đầu vào của bạn, và bạn biết nó sẽ luôn là yyyy-mm-ddThh: mm: ss và GMT (Z), bạn có thể trích xuất các chữ số từ mỗi thành viên và so sánh chúng như số nguyên

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

Nếu ngày có thể được định dạng khác nhau, bạn có thể cần thêm một cái gì đó cho iso thách thức folks:

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

Bạn không thể sử dụng ['Date.parse'] (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/parse)? –

14

Dưới đây là một phiên bản sửa đổi nhẹ của @David Brainer-Bankers answer sắp xếp theo thứ tự bảng chữ cái theo chuỗi hoặc số theo số và đảm bảo rằng các từ bắt đầu bằng chữ cái viết hoa không sắp xếp các từ bắt đầu bằng chữ cái viết thường (ví dụ: táo, sớm) sẽ được hiển thị theo thứ tự đó).

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

Giải pháp được đề xuất có thể gây ra lỗi nếu [khóa] và b [khóa] không phải là cả hai chuỗi. Tôi đề nghị thay thế y = y.toLowerCase() bằng y = ("" + y). ToLowerCase() – user8074

0

Bạn có thể tạo ra một đóng cửa và vượt qua nó như vậy here is my example working

$.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)); 
}); 
8

Sử dụng gạch chân js hoặc lodash,

var arrObj = [ 
    { 
     "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" 
    } 
]; 

arrObj = _.sortBy(arrObj,"updated_at"); 

_.sortBy() trả về một mảng mới

tham khảo http://underscorejs.org/#sortBy và tài liệu lodash https://lodash.com/docs#sortBy

0

Với sự hỗ trợ ES2015 nó có thể được thực hiện bằng cách:

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

không cần nội tuyến nếu thay thế

+0

Cảm ơn bạn đã giải thích – knowbody

+0

nếu updated_at là một thời gian ISO này sẽ không Ví dụ này giả định các dấu thời gian của Unix nhưng dữ liệu OP được đăng ở định dạng ISO. Vì vậy, bạn sẽ phải chuyển đổi sang các dấu thời gian của Unix để thực hiện so sánh.Điều này có thể được thực hiện với 'new Date (iso_str) .getTime()' này sẽ trả lại dấu thời gian của Unix –

6

Phương pháp Array.sort() sắp xếp các yếu tố của một mảng tại chỗ và trả về mảng. Hãy cẩn thận với Array.sort() vì nó không phải là Immutable. Để sử dụng loại không thay đổi immutable-sort.

Phương pháp này là sắp xếp mảng bằng cách sử dụng updated_at hiện tại ở định dạng ISO. Chúng tôi sử dụng new Data(iso_string).getTime() để chuyển đổi thời gian ISO thành dấu thời gian Unix. Dấu thời gian của Unix là một số mà chúng ta có thể làm toán đơn giản.Chúng tôi trừ dấu thời gian đầu tiên và thứ hai kết quả là; nếu dấu thời gian đầu tiên lớn hơn giây thứ hai thì số trả về sẽ là số dương. Nếu số thứ hai lớn hơn giá trị trả về đầu tiên sẽ là số âm. Nếu hai là cùng một sự trở lại sẽ bằng không. Điều này sẽ hoàn hảo với các giá trị trả về yêu cầu cho hàm inline.

Đối ES6:

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

Đối ES5:

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

Nếu bạn thay đổi updated_at của bạn sẽ được unix dấu thời gian bạn có thể làm điều này:

Đối ES6:

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

Đối ES5:

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

Vào thời điểm bài viết này, trình duyệt hiện đại không hỗ trợ ES6. Để sử dụng ES6 trong trình duyệt hiện đại, hãy sử dụng babel để chuyển mã thành ES5. Mong đợi hỗ trợ trình duyệt cho ES6 trong tương lai gần.

Array.sort() nên receave một giá trị trả về của một trong 3 khả năng xảy ra:

  • Một số dương (mục đầu tiên> mục thứ hai)
  • Một số tiêu cực (đầu mục < mục thứ hai)
  • 0 nếu hai mục là bằng nhau

Lưu ý rằng giá trị trả về trên hàm nội tuyến có thể có số dương hoặc âm. Array.Sort() không quan tâm đến số trả về của . Nó chỉ quan tâm nếu giá trị trả lại là dương, âm hoặc không.

Đối với loại Immutable: (ví dụ trong ES6)

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

Bạn cũng có thể viết nó theo cách này:

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

Việc nhập khẩu-từ mà bạn nhìn thấy là một cách mới để bao gồm javascript trong ES6 và làm cho mã của bạn trông rất sạch sẽ. Yêu thích cá nhân của tôi.

Loại không thể loại bỏ không làm thay đổi mảng nguồn thay vì trả về một mảng mới. Sử dụng const được khuyến nghị trên dữ liệu không thay đổi được.

1

Chỉ khác, hơn toán học, cách làm điều tương tự nhưng ngắn:

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

hoặc trong trơn lambda mũi tên phong cách:

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

này phương pháp có thể được thực hiện với bất kỳ đầu vào số

+0

câu trả lời được gạch dưới –

+0

Cảm ơn @ two7s_clash, tôi thực sự đánh giá cao nó !!! –

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

Như This bang câu trả lời của , bạn có thể sử dụng 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);

Các vấn đề liên quan