对象数组按对象指定属性排序——js实现

引入

  说明:使用语言为js。
  对象数组,即数组中存放的元素是一个个对象。例如

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" }
];

  但是我们可能需要对该对数组中对象的指定属性进行排序,例如上述对象数组中的age,birthday。如何操作?方法之一,就是数组的sort()方法。
  下面,就一步步去分析,实现一份简单通用的对象数组排序方法。

实现对象数组排序

第一步:简单排序number属性

  因为Array.sort()的“默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的”。好在是sort()方法接受一个用来指定按某种顺序进行排列的函数作为可选参数,即arr.sort([compareFunction])如果 compareFunction(a, b) 小于0,那么a会被排列到b之前;所以可以在此实现自己想要的排序方法。
注意,sort方法会改变原数组。(sort() 方法用原地算法对数组的元素进行排序,并返回数组。)

  话不多说,直接看。
  例如上述objArr,按照age升序排序:

// 指定排序的比较函数
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); 

  应该会得到如下结果:

按照age排序.png

第二阶段:可以排序string属性

  但是这个写法只能对age这个number类型的属性其作用,如果换成name或者birthday等,就不行,因为string不能直接用'-'比较得出大小。
  例如,运行console.log('male' - 'female');,应该会看到得出的是NaN。
  string,就应该使用localeCompare() 方法,它返回一个数字来指示一个参考字符串是否在排序顺序前面或之后或与给定字符串相同。完整语法:referenceStr.localeCompare(compareString[, locales[, options]])

  所以需要简单修改一下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); 

  结果应当如下:

按照birthday排序.png

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

  既然已经到了这个程度,那可以再加一个是按照升序或者降序排列。
  简单修改如下:

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); 

  得到的结果应该如下:

按birthday降序排序.png

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

  反正都这样了,再简单封装一下,导出成一个方法,后续直接使用。

  新建一个objArraySort.js,放入以下代码:

// sort使用的排序方法
// 传入对象数组用于排序的对象的属性,升序/降序
function compare(property, sortType = "asc") {

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

    return function (object1, object2) {
        // 取得对象属性值
        let value1 = object1[property];
        let value2 = object2[property];

        // 如果该对象不存在这个属性,也不做后续比较
        if (!value1 || !value2) {
            return;
        }

        // 如果两个属性取得的值不是一个类型的就不用比较了
        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;
        }
    }
}

// 通用方法,需要传入 需要排序的对象数组、对象属性、排序方式
function objectArraySort(array, property, sortType) {

    // 如果不是对象数组用这个方法,返回的是undefined
    if (!(array instanceof Array)) {
        return;
    }

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

// 导出
module.exports = {
    objectArraySort: objectArraySort,
}

  再将刚刚的objArr按照age降序排序:

// 引入模块
const oas = require("./objectArraySort");
// 调用方法,传入需要排序的对象数组、对象属性、排序方式
let sortObj = oas.objectArraySort(objArr, 'age', 'desc');
console.log(sortObj); 

  应该会得到以下结果:


按照age降序排序.png

  至此,一个简单通用的对象数组按照其对象指定属性排序的模块就完成了。实践有效,如果有问题,可提出交流,谢谢。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容