Javascript sắp xếp mảng theo hai trường


88
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);      
    return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;
});

Vì vậy, đoạn mã trên sắp xếp mảng theo gsize - nhỏ nhất đến lớn nhất. Nó hoạt động tốt. Nhưng nếu kích thước gs giống nhau, tôi muốn nó sắp xếp theo độ sáng.

Cảm ơn.


chức năng sắp xếp phản ứng trên kết quả dương, âm hoặc bằng không. vì vậy bạn chỉ cần viết: "return aSize - bSize". nó sẽ là mã đơn giản và dễ đọc hơn.

Câu trả lời:


107
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    var aLow = a.glow;
    var bLow = b.glow;
    console.log(aLow + " | " + bLow);

    if(aSize == bSize)
    {
        return (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0;
    }
    else
    {
        return (aSize < bSize) ? -1 : 1;
    }
});

170
grouperArray.sort(function (a, b) {   
    return a.gsize - b.gsize || a.glow - b.glow;
});

phiên bản ngắn hơn


đường tắt tuyệt vời! đã giúp tôi đưa ra một giải pháp phức tạp hơn cùng .. stackoverflow.com/questions/6101475/...
Joseph Poirier

3
Đẹp và sạch sẽ! Điều duy nhất nó chỉ hoạt động cho các con số.
Afanasii Kurakin

Bạn có thể giải thích logic ở đây không?!. Nó làm việc cho tôi sort an array with a key's value firstvà sau đósort the result with another key's value
KTM

1
@KTM Logic diễn ra như sau: nếu cả hai gsize đều bằng nhau, thì phần đầu tiên của điều kiện bằng 0, được coi là sai và phần thứ hai của điều kiện được thực thi.
Scalpweb

@Scalpweb Yeah :) vì vậy điều này hoạt động để sắp xếp một mảng với bất kỳ số lượng khóa từng cái một phải không ?! Bí quyết đẹp
KTM 21/05

35
grouperArray.sort((a, b) => a.gsize - b.gsize || a.glow - b.glow);

Phiên bản ngắn hơn sử dụng cú pháp mũi tên!


3
Ngắn gọn nhất và có thể mở rộng, hoàn hảo!
Laurent

1
Ngắn hơn nữa, hãy loại bỏ khoảng trống:grouperArray.sort((a,b)=>a.gsize-b.gsize||a.glow-b.glow);
Captain Fantastic

nếu bạn muốn hiểu tại sao nó hoạt động, bạn có thể muốn xem medium.com/@safareli/pss-ordering-is-a-monoid-61a4029387e
Safareli

14

Tôi nhận ra điều này đã được hỏi một thời gian trước, nhưng tôi nghĩ rằng tôi sẽ thêm giải pháp của mình.

Hàm này tạo ra các phương thức sắp xếp động. chỉ cần cung cấp từng tên thuộc tính con có thể sắp xếp, được thêm vào trước +/- để biểu thị thứ tự tăng dần hoặc giảm dần. Siêu tái sử dụng và nó không cần biết bất cứ điều gì về cấu trúc dữ liệu bạn đã tổng hợp lại. Có thể được làm bằng chứng ngu ngốc - nhưng dường như không cần thiết.

function getSortMethod(){
    var _args = Array.prototype.slice.call(arguments);
    return function(a, b){
        for(var x in _args){
            var ax = a[_args[x].substring(1)];
            var bx = b[_args[x].substring(1)];
            var cx;

            ax = typeof ax == "string" ? ax.toLowerCase() : ax / 1;
            bx = typeof bx == "string" ? bx.toLowerCase() : bx / 1;

            if(_args[x].substring(0,1) == "-"){cx = ax; ax = bx; bx = cx;}
            if(ax != bx){return ax < bx ? -1 : 1;}
        }
    }
}

ví dụ sử dụng:

items.sort (getSortMethod ('- price', '+ priority', '+ name'));

điều này sẽ sắp xếp itemsvới mục thấp nhất pricetrước tiên, với các mối quan hệ sẽ đến mục có giá trị cao nhất priority. mối quan hệ hơn nữa bị phá vỡ bởi mụcname

trong đó các mục là một mảng như:

var items = [
    { name: "z - test item", price: "99.99", priority: 0, reviews: 309, rating: 2 },
    { name: "z - test item", price: "1.99", priority: 0, reviews: 11, rating: 0.5 },
    { name: "y - test item", price: "99.99", priority: 1, reviews: 99, rating: 1 },
    { name: "y - test item", price: "0", priority: 1, reviews: 394, rating: 3.5 },
    { name: "x - test item", price: "0", priority: 2, reviews: 249, rating: 0.5 } ...
];

bản demo trực tiếp: http://gregtaff.com/misc/multi_field_sort/

CHỈNH SỬA: Đã khắc phục sự cố với Chrome.


Điều này thật tuyệt vời
Azure

Câu trả lời thiên tài!
Marius

đối với bản ghi (vì không nhận được error TS2554: Expected 0 arguments, but got ..), hãy sử dụng cú pháp tại đây: stackoverflow.com/a/4116634/5287221
Chananel P

6

Tôi mong rằng nhà điều hành bậc ba((aSize < bSize) ? -1 : (aSize > bSize) ? 1 : 0;) đã khiến bạn nhầm lẫn. Bạn nên xem liên kết để hiểu rõ hơn.

Cho đến lúc đó, đây là mã của bạn đã hoàn thành nếu / else.

grouperArray.sort(function (a, b) {
    if (a.gsize < b.gsize)
    {
        return -1;
    }
    else if (a.gsize > b.gsize)
    {
        return 1;
    }
    else
    {
        if (a.glow < b.glow)
        {
            return -1;
        }
        else if (a.glow > b.glow)
        {
            return 1;
        }
        return 0;
    }
});

6

Đây là cách triển khai dành cho những người có thể muốn thứ gì đó chung chung hơn có thể hoạt động với bất kỳ số lượng trường nào.

Array.prototype.sortBy = function (propertyName, sortDirection) {

    var sortArguments = arguments;
    this.sort(function (objA, objB) {

        var result = 0;
        for (var argIndex = 0; argIndex < sortArguments.length && result === 0; argIndex += 2) {

            var propertyName = sortArguments[argIndex];
            result = (objA[propertyName] < objB[propertyName]) ? -1 : (objA[propertyName] > objB[propertyName]) ? 1 : 0;

            //Reverse if sort order is false (DESC)
            result *= !sortArguments[argIndex + 1] ? 1 : -1;
        }
        return result;
    });

}

Về cơ bản, bạn có thể chỉ định bất kỳ số lượng tên thuộc tính / hướng sắp xếp nào:

var arr = [{
  LastName: "Doe",
  FirstName: "John",
  Age: 28
}, {
  LastName: "Doe",
  FirstName: "Jane",
  Age: 28
}, {
  LastName: "Foo",
  FirstName: "John",
  Age: 30
}];

arr.sortBy("LastName", true, "FirstName", true, "Age", false);
//Will return Jane Doe / John Doe / John Foo

arr.sortBy("Age", false, "LastName", true, "FirstName", false);
//Will return John Foo / John Doe / Jane Doe

3
grouperArray.sort(function (a, b) {
  var aSize = a.gsize;
  var bSize = b.gsize;
  var aLow = a.glow;
  var bLow = b.glow;
  console.log(aLow + " | " + bLow);      
  return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : ( (aLow < bLow ) ? -1 : (aLow > bLow ) ? 1 : 0 );
});

3
grouperArray.sort(function (a, b) {
     var aSize = a.gsize;     
     var bSize = b.gsize;     
     var aLow = a.glow;
     var bLow = b.glow;
     console.log(aLow + " | " + bLow);
     return (aSize < bSize) ? -1 : (aSize > bSize) ? 1 : (aLow < bLow) ? -1 : (aLow > bLow) ? 1 : 0); }); 

3

Đây là một triển khai sử dụng đệ quy để sắp xếp theo bất kỳ số trường sắp xếp nào từ 1 đến vô hạn. Bạn chuyển cho nó một mảng kết quả là một mảng các đối tượng kết quả để sắp xếp và một mảng sắp xếp là một mảng các đối tượng sắp xếp xác định cách sắp xếp. Mỗi đối tượng sắp xếp phải có khóa "chọn" cho tên khóa mà nó sắp xếp theo và khóa "thứ tự" là một chuỗi cho biết "tăng dần" hoặc "giảm dần".

sortMultiCompare = (a, b, sorts) => {
    let select = sorts[0].select
    let order = sorts[0].order
    if (a[select] < b[select]) {
        return order == 'ascending' ? -1 : 1
    } 
    if (a[select] > b[select]) {
        return order == 'ascending' ? 1 : -1
    }
    if(sorts.length > 1) {
        let remainingSorts = sorts.slice(1)
        return this.sortMultiCompare(a, b, remainingSorts)
    }
    return 0
}

sortResults = (results, sorts) => {
    return results.sort((a, b) => {
        return this.sortMultiCompare(a, b, sorts)
    })
}

// example inputs
const results = [
    {
        "LastName": "Doe",
        "FirstName": "John",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Doe",
        "FirstName": "Jane",
        "MiddleName": "Bill"
    },
    {
        "LastName": "Johnson",
        "FirstName": "Kevin",
        "MiddleName": "Bill"
    }
]

const sorts = [
    {
        "select": "LastName",
        "order": "ascending"
    },
    {
        "select": "FirstName",
        "order": "ascending"
    },
    {
        "select": "MiddleName",
        "order": "ascending"
    }    
]

// call the function like this:
let sortedResults = sortResults(results, sorts)

2

Một cách năng động để làm điều đó với NHIỀU phím:

  • lọc các giá trị duy nhất từ ​​mỗi cột / khóa sắp xếp
  • đặt theo thứ tự hoặc đảo ngược nó
  • thêm zeropad chiều rộng trọng số cho từng đối tượng dựa trên các giá trị của khóa indexOf (value)
  • sắp xếp bằng cách sử dụng các trọng số được caclutated

nhập mô tả hình ảnh ở đây

Object.defineProperty(Array.prototype, 'orderBy', {
value: function(sorts) { 
    sorts.map(sort => {            
        sort.uniques = Array.from(
            new Set(this.map(obj => obj[sort.key]))
        );

        sort.uniques = sort.uniques.sort((a, b) => {
            if (typeof a == 'string') {
                return sort.inverse ? b.localeCompare(a) : a.localeCompare(b);
            }
            else if (typeof a == 'number') {
                return sort.inverse ? (a < b) : (a > b ? 1 : 0);
            }
            else if (typeof a == 'boolean') {
                let x = sort.inverse ? (a === b) ? 0 : a? -1 : 1 : (a === b) ? 0 : a? 1 : -1;
                return x;
            }
            return 0;
        });
    });

    const weightOfObject = (obj) => {
        let weight = "";
        sorts.map(sort => {
            let zeropad = `${sort.uniques.length}`.length;
            weight += sort.uniques.indexOf(obj[sort.key]).toString().padStart(zeropad, '0');
        });
        //obj.weight = weight; // if you need to see weights
        return weight;
    }

    this.sort((a, b) => {
        return weightOfObject(a).localeCompare( weightOfObject(b) );
    });

    return this;
}
});

Sử dụng:

// works with string, number and boolean
let sortered = your_array.orderBy([
    {key: "type", inverse: false}, 
    {key: "title", inverse: false},
    {key: "spot", inverse: false},
    {key: "internal", inverse: true}
]);

nhập mô tả hình ảnh ở đây


1

Đây là những gì tôi sử dụng

function sort(a, b) {
    var _a = "".concat(a.size, a.glow);
    var _b = "".concat(b.size, b.glow);
    return _a < _b;
}

nối hai mục dưới dạng một chuỗi và chúng sẽ được sắp xếp theo một giá trị chuỗi. Nếu bạn muốn, bạn có thể bọc _a và _b bằng parseInt để so sánh chúng dưới dạng số nếu bạn biết chúng sẽ là số.


1

Đây là giải pháp cho trường hợp bạn có khóa sắp xếp ưu tiên, khóa này có thể không tồn tại trong một số mục cụ thể, vì vậy bạn phải sắp xếp theo khóa dự phòng.

Ví dụ về dữ liệu đầu vào ( id2 là khóa sắp xếp ưu tiên):

const arr = [
    {id: 1},
    {id: 2, id2: 3},
    {id: 4},
    {id: 3},
    {id: 10, id2: 2},
    {id: 7},
    {id: 6, id2: 1},
    {id: 5},
    {id: 9, id2: 2},
    {id: 8},
];

Và đầu ra phải là:

[ { id: 6, id2: 1 },
  { id: 9, id2: 2 },
  { id: 10, id2: 2 },
  { id: 2, id2: 3 },
  { id: 1 },
  { id: 3 },
  { id: 4 },
  { id: 5 },
  { id: 7 },
  { id: 8 } ]

Hàm so sánh sẽ giống như sau:

arr.sort((a,b) => {
  if(a.id2 || b.id2) {
    if(a.id2 && b.id2) {
      if(a.id2 === b.id2) {
        return a.id - b.id;
      }
      return a.id2 - b.id2;
    }
    return a.id2 ? -1 : 1;
  }
  return a.id - b.id
});

PS Trong trường hợp nếu .id của .id2 có thể là số 0, hãy cân nhắc sử dụng typeof.


0
grouperArray.sort(
  function(a,b){return a.gsize == b.gsize ? a.glow - b.glow : a.gsize - b.gsize}
);

0
grouperArray.sort(function (a, b) {
    var aSize = a.gsize;
    var bSize = b.gsize;
    if (aSize !== aSize)
        return aSize - bSize;
    return a.glow - b.glow;
});

không được thử nghiệm, nhưng tôi nghĩ rằng điều đó sẽ hoạt động.


0

Trong trường hợp của tôi, tôi sắp xếp danh sách thông báo theo thông số 'quan trọng' và theo 'ngày tháng'

  • bước 1: Tôi lọc thông báo theo 'quan trọng' và không quan trọng

    let importantNotifications = notifications.filter(
            (notification) => notification.isImportant);
    
      let unImportantNotifications = notifications.filter(
            (notification) => !notification.isImportant);
    
  • bước 2: tôi sắp xếp chúng theo ngày

      sortByDate = (notifications) => {
      return notifications.sort((notificationOne, notificationTwo) => {
        return notificationOne.date - notificationTwo.date;
      });
    };
    
  • bước 3: hợp nhất chúng

    [
        ...this.sortByDate(importantNotifications),
        ...this.sortByDate(unImportantNotifications),
      ];
    
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.