Làm cách nào tôi có thể thực hiện sắp xếp asc và desc bằng underscore.js?


166

Tôi hiện đang sử dụng dấu gạch dưới để sắp xếp json sắp xếp của tôi. Bây giờ tôi đã yêu cầu thực hiện ascendingdescendingsắp xếp bằng cách sử dụng underscore.js. Tôi không thấy bất cứ điều gì liên quan đến cùng trong tài liệu. Làm thế nào tôi có thể đạt được điều này?


1
Vui lòng thêm một ví dụ về những gì bạn đang sắp xếp và làm thế nào.
Jon

Bạn đang sắp xếp cái gì? Số? Dây? Ngày? Thứ gì khác?
mu quá ngắn

@muistooshort Tôi đang sắp xếp một mảng các đối tượng. Vì vậy, phương thức sortBy phù hợp hoàn hảo với tiêu chí của tôi để sắp xếp tăng dần nhưng không phải là cách khác.
La Mã

Nếu bạn sắp xếp theo một số thì sortBychức năng của bạn có thể return -nnhưng điều đó sẽ không hoạt động đối với các chuỗi; do đó câu hỏi về những thứ bạn sắp xếp.
mu quá ngắn

2
Với Lodash, bạn có thể sử dụng tốc ký như _.sortBy([1,4,3,2]).reverse()hoặc _.chain([1,4,3,2]).sortBy().reverse().value()nếu bạn không muốn sử dụng reverse()nguyên mẫu của Array.
GFoley83

Câu trả lời:


363

Bạn có thể sử dụng .sortBy, nó sẽ luôn trả về một danh sách tăng dần :

_.sortBy([2, 3, 1], function(num) {
    return num;
}); // [1, 2, 3]

Nhưng bạn có thể sử dụng phương thức .reverse để làm cho nó giảm dần :

var array = _.sortBy([2, 3, 1], function(num) {
    return num;
});

console.log(array); // [1, 2, 3]
console.log(array.reverse()); // [3, 2, 1]

Hoặc khi giao dịch với các số, thêm dấu âm vào biểu đồ để xuống danh sách:

_.sortBy([-3, -2, 2, 3, 1, 0, -1], function(num) {
    return -num;
}); // [3, 2, 1, 0, -1, -2, -3]

Dưới mui xe .sortBysử dụng tích hợp .sort([handler]):

// Default is ascending:
[2, 3, 1].sort(); // [1, 2, 3]

// But can be descending if you provide a sort handler:
[2, 3, 1].sort(function(a, b) {
    // a = current item in array
    // b = next item in array
    return b - a;
});

9
Giải pháp cuối cùng tức là thêm dấu hiệu chú thích vào num trả về là hoàn hảo.
vinesh

Tại sao bạn nghĩ rằng đó là loại bong bóng? Theo các .sortBy()cuộc gọi được tích hợp sẵn Array.sort(), thuật toán tùy thuộc vào các nhà cung cấp trình duyệt, nhưng sắp xếp bong bóng rất khó có thể là lựa chọn của họ.
Rene Saarsoo

Điều này không làm tăng sự phức tạp thời gian? Nó làm cho danh sách được sắp xếp hai lần.
user1477388

@ user1477388 Tôi không chắc ý của bạn về việc sắp xếp hai lần?
andlrc

@andlrc Vì vậy, khi bạn gọi _.sortBy(arr, function), tôi giả sử nó lặp qua từng mục và thực thi một số logic để trả về mảng đã sắp xếp. Sau đó, khi bạn gọi Array.prototype.reverse()nó có thể lặp lại từng mục một lần nữa và thực hiện một số logic để trả về mảng đảo ngược. Do đó, bạn đang lặp lại mảng hai lần.
user1477388

57

Thứ tự giảm dần sử dụng dấu gạch dưới có thể được thực hiện bằng cách nhân giá trị trả về với -1.

//Ascending Order:
_.sortBy([2, 3, 1], function(num){
    return num;
}); // [1, 2, 3]


//Descending Order:
_.sortBy([2, 3, 1], function(num){
    return num * -1;
}); // [3, 2, 1]

Nếu bạn sắp xếp theo chuỗi không phải là số, bạn có thể sử dụng phương thức charCodeAt () để lấy giá trị unicode.

//Descending Order Strings:
_.sortBy(['a', 'b', 'c'], function(s){ 
    return s.charCodeAt() * -1;
});

3
Tôi đang cố gắng sắp xếp theo thứ tự bảng chữ cái - nhân với -1 không phải là một hoạt động hợp lệ. :)
rythos42

Đó là một trường hợp đáng sử dụng trong khi sử dụng nhưng không được chỉ định trong câu hỏi. Tuy nhiên, nhân một chuỗi với -1 là một hoạt động hợp lệ. Nó trả về NaN, đó là một kết quả hợp lệ.
jEremyB

1
nhớ gán lại mảng quá! SOME_ARR = _.sortBy (SOME_ARR, hàm (num) {SOME_FUNC ...});
aqm

4
charCodeAt sẽ "trả về Unicode của ký tự theo chỉ mục được chỉ định trong một chuỗi" để nó có thể được sử dụng để sắp xếp theo các ký tự trong một chuỗi, nhưng như được hiển thị, nó không "sắp xếp theo chuỗi" mà nó sắp xếp theo một ký tự trong chuỗi
Anthony

2
Điều này chỉ sắp xếp theo ký tự đầu tiên, và nó là trường hợp nhạy cảm.
Aidan

50

Các Array Avatar của nguyên mẫu phương pháp ngược Sửa đổi mảng và trả về một tham chiếu đến nó, có nghĩa là bạn có thể làm điều này:

var sortedAsc = _.sortBy(collection, 'propertyName');
var sortedDesc = _.sortBy(collection, 'propertyName').reverse();

Ngoài ra, tài liệu gạch dưới đọc:

Ngoài ra, các phương thức của nguyên mẫu Array được ủy quyền thông qua đối tượng Underscore được xâu chuỗi, do đó bạn có thể trượt một reversehoặc một pushchuỗi vào chuỗi của mình và tiếp tục sửa đổi mảng.

có nghĩa là bạn cũng có thể sử dụng .reverse()trong khi xâu chuỗi:

var sortedDescAndFiltered = _.chain(collection)
    .sortBy('propertyName')
    .reverse()
    .filter(_.property('isGood'))
    .value();

Đây là phương pháp đơn giản nhất để sắp xếp ngược / giảm dần khi nói đến hầu hết các trường hợp sử dụng đơn giản.
Dan Atkinson

2
Để thực hiện một loại bảng chữ cái không phân biệt chữ hoa chữ thường:_.sortBy(collection, item => item. propertyName.toLowerCase());
XåpplI'-I0llwlg'I -

điều này không hoạt động nếu có số âm trong mảng.
Shruti Kapoor

@ShrutiKapoor Có. Tại sao không?
Emil Lundberg

5
Hiệu suất khôn ngoan, trước tiên nên áp dụng bộ lọc và sau đó sắp xếp các giá trị (phần còn lại).
Saran

12

Tương tự như thư viện Underscore, có một thư viện khác gọi là 'lodash' có một phương thức "orderBy" lấy tham số để xác định thứ tự sắp xếp nó. Bạn có thể sử dụng nó như

_.orderBy('collection', 'propertyName', 'desc')

Vì một số lý do, nó không được ghi lại trên tài liệu của trang web.


Tôi nghĩ rằng bạn nhầm lẫn gạch dưới với lodash . Chỉ sau này có chức năng orderBy được đề cập .
Thomas Marti

Vâng, xấu của tôi. Sẽ cập nhật câu trả lời. Cảm ơn đã sửa lỗi :)
Minkesh Jain

orderBy, siêu hữu ích! Tốt hơn nhiều so với sử dụng ngược lại, vì nó bảo toàn thuộc tính sắp xếp ổn định mà tôi đang tìm kiếm.
Flimm

Không làm việc cho tôi vì một số lý do upadte: lodash của nó (
aleXela

0

Mixins gạch dưới

Mở rộng câu trả lời của @ emil_lundberg, bạn cũng có thể viết "mixin" nếu bạn đang sử dụng Underscore để tạo một chức năng tùy chỉnh để sắp xếp nếu đó là một loại sắp xếp bạn có thể lặp lại trong một ứng dụng ở đâu đó.

Ví dụ: có thể bạn có bộ điều khiển hoặc xem kết quả sắp xếp theo thứ tự sắp xếp "ASC" hoặc "DESC" và bạn muốn chuyển đổi giữa loại đó, bạn có thể làm một cái gì đó như thế này:

Mixin.js

_.mixin({
    sortByOrder: function(stooges, prop, order) {
      if (String(order) === "desc") {
          return _.sortBy(stooges, prop).reverse();
      } else if (String(order) === "asc") {
          return _.sortBy(stooges, prop);
      } else {
          return stooges;
      }
    }
})

Ví dụ sử dụng

var sort_order = "asc";
var stooges = [
  {name: 'moe', age: 40}, 
  {name: 'larry', age: 50}, 
  {name: 'curly', age: 60},
  {name: 'July', age: 35},
  {name: 'mel', age: 38}
 ];

_.mixin({
    sortByOrder: function(stooges, prop, order) {
    if (String(order) === "desc") {
        return _.sortBy(stooges, prop).reverse();
    } else if (String(order) === "asc") {
        return _.sortBy(stooges, prop);
    } else {
        return stooges;
    }
  }
})


// find elements
var banner = $("#banner-message");
var sort_name_btn = $("button.sort-name");
var sort_age_btn = $("button.sort-age");

function showSortedResults(results, sort_order, prop) {
    banner.empty();
    banner.append("<p>Sorting: " + prop + ', ' + sort_order + "</p><hr>")
  _.each(results, function(r) {
    banner.append('<li>' + r.name + ' is '+ r.age + ' years old.</li>');
  }) 
}

// handle click and add class
sort_name_btn.on("click", function() {
  sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'name', sort_order);
  showSortedResults(sortedResults, sort_order, 'name');
})

sort_age_btn.on('click', function() {
    sort_order = (sort_order === "asc") ? "desc" : "asc"; 
    var sortedResults = _.sortByOrder(stooges, 'age', sort_order);
  showSortedResults(sortedResults, sort_order, 'age');
})

Đây là một JSFiddle chứng minh điều này: JSFiddle cho SortBy Mixin

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.