對(duì)象數(shù)組按對(duì)象指定屬性排序——js實(shí)現(xiàn)

引入

??說(shuō)明:使用語(yǔ)言為js。
??對(duì)象數(shù)組,即數(shù)組中存放的元素是一個(gè)個(gè)對(duì)象。例如

let objArr = [
    { name: "張三", sex: 'female', age: 30, birthday: "1994/10/11" },
    { name: "李四", sex: 'male', age: 20, birthday: "2001/08/11" },
    { name: "王五", sex: 'female', age: 40, birthday: "2001/01/15" }
];

??但是我們可能需要對(duì)該對(duì)數(shù)組中對(duì)象的指定屬性進(jìn)行排序,例如上述對(duì)象數(shù)組中的age,birthday。如何操作?方法之一,就是數(shù)組的sort()方法。
??下面,就一步步去分析,實(shí)現(xiàn)一份簡(jiǎn)單通用的對(duì)象數(shù)組排序方法。

實(shí)現(xiàn)對(duì)象數(shù)組排序

第一步:簡(jiǎn)單排序number屬性

??因?yàn)锳rray.sort()的“默認(rèn)排序順序是在將元素轉(zhuǎn)換為字符串,然后比較它們的UTF-16代碼單元值序列時(shí)構(gòu)建的”。好在是sort()方法接受一個(gè)用來(lái)指定按某種順序進(jìn)行排列的函數(shù)作為可選參數(shù),即arr.sort([compareFunction]),如果 compareFunction(a, b) 小于0,那么a會(huì)被排列到b之前;所以可以在此實(shí)現(xiàn)自己想要的排序方法。
注意,sort方法會(huì)改變?cè)瓟?shù)組。(sort() 方法用原地算法對(duì)數(shù)組的元素進(jìn)行排序,并返回?cái)?shù)組。)

??話不多說(shuō),直接看。
??例如上述objArr,按照age升序排序:

// 指定排序的比較函數(shù)
function compare(property) {
    return function (object1, object2) {
        let value1 = object1[property];
        let value2 = object2[property];
        // 升序
        return value1 - value2;
    }
}
let sortObj = objArr.sort(compare("age"));
console.log(sortObj); 

??應(yīng)該會(huì)得到如下結(jié)果:

按照age排序.png

第二階段:可以排序string屬性

??但是這個(gè)寫法只能對(duì)age這個(gè)number類型的屬性其作用,如果換成name或者birthday等,就不行,因?yàn)閟tring不能直接用'-'比較得出大小。
??例如,運(yùn)行console.log('male' - 'female');,應(yīng)該會(huì)看到得出的是NaN。
??string,就應(yīng)該使用localeCompare() 方法,它返回一個(gè)數(shù)字來(lái)指示一個(gè)參考字符串是否在排序順序前面或之后或與給定字符串相同。完整語(yǔ)法:referenceStr.localeCompare(compareString[, locales[, options]])。

??所以需要簡(jiǎn)單修改一下compare()方法,修改如下:

function compare(property) {
    return function (object1, object2) {
        let value1 = object1[property];
        let value2 = object2[property];

        if (typeof (value1) == typeof (value2)) {
            if (typeof (value1) === 'number') {
                return value1 - value2;
            }
            if (typeof (value1) === 'string') {
                // 升序
                return value1.toString().localeCompare(value2);
            }
        }
    }
}

let sortObj = objArr.sort(compare("birthday"));
console.log(sortObj); 

??結(jié)果應(yīng)當(dāng)如下:

按照birthday排序.png

第三階段:可以指定升序/降序

??既然已經(jīng)到了這個(gè)程度,那可以再加一個(gè)是按照升序或者降序排列。
??簡(jiǎn)單修改如下:

function compare(property, sortType = "asc") {

    return function (object1, object2) {
        let value1 = object1[property];
        let value2 = object2[property];

        // 判斷 傳入的屬性值 是number還是 string
        if (typeof (value1) == typeof (value2)) {
            if (typeof (value1) === 'number') {
                // 如果是升序
                if (sortType === "asc") {
                    return value1 - value2;
                } else if (sortType === "desc") {
                    // 如果是降序
                    return value2 - value1;
                }
            }
            if (typeof (value1) === 'string') {
                // 如果是升序
                if (sortType === "asc") {
                    return value1.toString().localeCompare(value2);
                } else if (sortType === "desc") {
                    // 如果是降序
                    return value2.toString().localeCompare(value1);
                }
            }
        }
    }
}
// 生日,降序
let sortObj = objArr.sort(compare("birthday", 'desc'));
console.log(sortObj); 

??得到的結(jié)果應(yīng)該如下:

按birthday降序排序.png

第四階段:封裝成通用方法

??反正都這樣了,再簡(jiǎn)單封裝一下,導(dǎo)出成一個(gè)方法,后續(xù)直接使用。

??新建一個(gè)objArraySort.js,放入以下代碼:

// sort使用的排序方法
// 傳入對(duì)象數(shù)組用于排序的對(duì)象的屬性,升序/降序
function compare(property, sortType = "asc") {

    // 如果不是 asc,desc,不做下一步比較
    if (!(sortType === "desc" || sortType === "asc")) {
        return;
    }

    return function (object1, object2) {
        // 取得對(duì)象屬性值
        let value1 = object1[property];
        let value2 = object2[property];

        // 如果該對(duì)象不存在這個(gè)屬性,也不做后續(xù)比較
        if (!value1 || !value2) {
            return;
        }

        // 如果兩個(gè)屬性取得的值不是一個(gè)類型的就不用比較了
        if (typeof (value1) == typeof (value2)) {

            // 判斷 傳入的屬性值 是number還是 string
            if (typeof (value1) === 'number') {
                // 如果是升序
                if (sortType === "asc") {
                    return value1 - value2;
                } else {
                    // 如果是降序
                    return value2 - value1;
                }
            } else if (typeof (value1) === 'string') {
                // 如果是升序
                if (sortType === "asc") {
                    return value1.toString().localeCompare(value2);
                } else {
                    // 如果是降序
                    return value2.toString().localeCompare(value1);
                }
            } else {
                // 其它類型就不排序了
                return;
            }
        } else {
            return;
        }
    }
}

// 通用方法,需要傳入 需要排序的對(duì)象數(shù)組、對(duì)象屬性、排序方式
function objectArraySort(array, property, sortType) {

    // 如果不是對(duì)象數(shù)組用這個(gè)方法,返回的是undefined
    if (!(array instanceof Array)) {
        return;
    }

    return array.sort(compare(property, sortType));
}

// 導(dǎo)出
module.exports = {
    objectArraySort: objectArraySort,
}

??再將剛剛的objArr按照age降序排序:

// 引入模塊
const oas = require("./objectArraySort");
// 調(diào)用方法,傳入需要排序的對(duì)象數(shù)組、對(duì)象屬性、排序方式
let sortObj = oas.objectArraySort(objArr, 'age', 'desc');
console.log(sortObj); 

??應(yīng)該會(huì)得到以下結(jié)果:


按照age降序排序.png

??至此,一個(gè)簡(jiǎn)單通用的對(duì)象數(shù)組按照其對(duì)象指定屬性排序的模塊就完成了。實(shí)踐有效,如果有問(wèn)題,可提出交流,謝謝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容