我有一个JavaScript对象数组:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];

如何在JavaScript中按last_nom的值对它们进行排序?

我知道排序(a,b),但这似乎只适用于字符串和数字。是否需要向对象添加toString()方法?


当前回答

示例用法:

objs.sort(sortBy('last_nom'));

脚本:

/**
 * @description
 * Returns a function which will sort an
 * array of objects by the given key.
 *
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}
 */
const sortBy = (key, reverse) => {

  // Move smaller items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveSmaller = reverse ? 1 : -1;

  // Move larger items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveLarger = reverse ? -1 : 1;

  /**
   * @param  {*} a
   * @param  {*} b
   * @return {Number}
   */
  return (a, b) => {
    if (a[key] < b[key]) {
      return moveSmaller;
    }
    if (a[key] > b[key]) {
      return moveLarger;
    }
    return 0;
  };
};

其他回答

我刚刚增强了EgeÖzcan的动态分类,可以深入物体内部。

如果数据如下所示:

obj = [
    {
        a: { a: 1, b: 2, c: 3 },
        b: { a: 4, b: 5, c: 6 }
    },
    {
        a: { a: 3, b: 2, c: 1 },
        b: { a: 6, b: 5, c: 4 }
}];

如果你想在a.a属性中进行排序,我认为我的增强功能非常有用。我向以下对象添加了新功能:

Object.defineProperty(Object.prototype, 'deepVal', {
    enumerable: false,
    writable: true,
    value: function (propertyChain) {
        var levels = propertyChain.split('.');
        parent = this;
        for (var i = 0; i < levels.length; i++) {
            if (!parent[levels[i]])
                return undefined;
            parent = parent[levels[i]];
        }
        return parent;
    }
});

并更改了_dynamicSort的返回函数:

return function (a, b) {
    var result = ((a.deepVal(property) > b.deepVal(property)) - (a.deepVal(property) < b.deepVal(property)));
    return result * sortOrder;
}

现在你可以这样按a.a.排序:

obj.sortBy('a.a');

在JSFiddle中查看完整的脚本。

我还没有看到这种特别的方法,所以这里有一个我喜欢使用的简洁的比较方法,它适用于字符串和数字类型:

常量对象=[{first_nom:'Lazslo',last_nom:'Jamf'},{first_nom:'猪',last_nom:'Bodine'},{first_nom:'海盗',last_nom:'Prentice'}];常量排序依据=fn=>{常量cmp=(a,b)=>-(a<b)||+(a>b);return(a,b)=>cmp(fn(a),fn(b));};const getLastName=o=>o.last_nom;const sortByLastName=sortBy(getLastName);objs.sort(sortByLastName);console.log(objs.map(getLastName));

sortBy()的解释

sortBy()接受一个fn,该fn从一个对象中选择一个值用于比较,并返回一个可以传递给Array.prototype.sort()的函数。在本例中,我们正在比较o.last_nom。每当我们收到两个对象,例如

a = { first_nom: 'Lazslo', last_nom: 'Jamf' }
b = { first_nom: 'Pig', last_nom: 'Bodine' }

我们将它们与(a,b)=>cmp(fn(a),fn(b))进行比较。鉴于此

fn = o => o.last_nom

我们可以将比较函数扩展为(a,b)=>cmp(a.last_nom,b.last_nom)。由于逻辑OR(||)在JavaScript中的工作方式,cmp(a.last_nom、b.last_nom)相当于

if (a.last_nom < b.last_nom) return -1;
if (a.last_nom > b.last_nom) return 1;
return 0;

顺便说一下,这在其他语言中被称为三向比较“宇宙飞船”(<=>)运算符。

最后,这里是不使用箭头函数的ES5兼容语法:

var对象=[{first_nom:'Lazslo',last_nom:'Jamf'},{first_nom:'猪',last_nom:'Bodine'},{first_nom:'海盗',last_nom:'Prentice'}];函数sortBy(fn){函数cmp(a,b){return-(a<b)| |+(a>b);}返回函数(a,b){return cmp(fn(a),fn(b));};}函数getLastName(o){return o.last_nom;}var sortByLastName=sortBy(getLastName);objs.sort(sortByLastName);console.log(objs.map(getLastName));

您可以使用可重用的排序函数。

Array.prototype.order = function (prop, methods = {}) {
    if (prop?.constructor == Object) {
        methods = prop;
        prop = null;
    }
    const [orderType_a, orderType_b] = methods.reverse ? [1, -1] : [-1, 1];

    const $ = x => prop
        ? methods.insensitive
            ? String(x[prop]).toLowerCase()
            : x[prop]
        : methods.insensitive
            ? String(x).toLowerCase()
            : x;

    const fn = (a, b) => $(a) < $(b) ? orderType_a : $(b) < $(a) ? orderType_b : 0;
    return this.sort(fn);
};

它可用于对数组和数组中的对象进行排序。

let items = [{ x: "Z" }, 3, "1", "0", 2, { x: "a" }, { x: 0 }];
items
    .order("x", { insensitive: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, '1', '0', 2, { x: 'Z' } ]
    .order({ reverse: 1 })
    // [ { x: 0 }, { x: 'a' }, 3, 2, { x: 'Z' }, '1', '0' ]
    .sort(x => typeof x == "string" || typeof x == "number" ? -1 : 0)
    // [ '0', '1', 2, 3, { x: 0 }, { x: 'a' }, { x: 'Z' } ]

1nd(可选)>对数组中包含的对象进行排序。2rd是方法>{reverse:any,不敏感:any}

这是我的看法:

order参数是可选的,对于升序,默认为“ASC”。

它适用于重音字符,并且不区分大小写。

注意:它排序并返回原始数组。

function sanitizeToSort(str) {
  return str
    .normalize('NFD')                   // Remove accented and diacritics
    .replace(/[\u0300-\u036f]/g, '')    // Remove accented and diacritics
    .toLowerCase()                      // Sort will be case insensitive
  ;
}

function sortByProperty(arr, property, order="ASC") {
  arr.forEach((item) => item.tempProp = sanitizeToSort(item[property]));
  arr.sort((a, b) => order === "ASC" ?
      a.tempProp > b.tempProp ?  1 : a.tempProp < b.tempProp ? -1 : 0
    : a.tempProp > b.tempProp ? -1 : a.tempProp < b.tempProp ?  1 : 0
  );
  arr.forEach((item) => delete item.tempProp);
  return arr;
}

一小条

函数cleaniteToSort(str){返回str.normalize('NFD')//删除重音字符.replace(/[\u0300-\u036f]/g,“”)//删除变音符号.to小写();}函数sortByProperty(arr,property,order=“ASC”){arr.forEach((item)=>item.tempProp=消毒排序(item[property]));arr.sort((a,b)=>顺序==“ASC”?a.tempProp>b.tempProp?1:a.tempProp<b.tempProp-1 : 0:a.tempProp>b.tempProp-1:a.tempProp<b.tempProp?1 : 0);arr.forEach((item)=>删除item.tempProp);返回arr;}常量rockStars=[{name:“Axl”,姓:“Rose”},{name:“埃尔顿”,姓:“John”},{name:“Paul”,姓氏:“McCartney”},{name:“楼”,姓:“里德”},{name:“freddie”,//使用小写/大写姓氏:“mercury”},{name:“Ámy”,//也适用于重音字符姓氏:“酒庄”}];sortByProperty(rockStars,“name”);console.log(“按名称A-Z排序:”);rockStars.forEach((item)=>console.log(item.name+“”+item.lastname));sortByProperty(rockStars,“姓氏”,“DESC”);console.log(“\n按姓氏Z-A排序:”);rockStars.forEach((item)=>console.log(item.lastname+“,”+item.name));

将Ege的动态解决方案与Vinay的想法相结合,您可以得到一个很好的鲁棒解决方案:

Array.prototype.sortBy=函数(){函数_sortByAttr(属性){var sortOrder=1;如果(属性[0]==“-”){sortOrder=-1;attr=attr.substr(1);}返回函数(a,b){var结果=(a[attr]<b[attr])-1:(a[attr]>b[attr])?1 : 0;返回结果*sortOrder;}}函数_getSortFunc(){if(arguments.length==0){throw“Array.sortBy()不允许零长度参数”;}var args=参数;返回函数(a,b){for(var result=0,i=0;result==0&&i<args.length;i++){result=_sortByAttr(args[i])(a,b);}返回结果;}}返回this.sort(_getSortFunc.apply(null,arguments));}用法://用于打印对象的实用程序Array.prototype.print=函数(标题){console.log(“************************************************************”);console.log(“***”+标题);console.log(“************************************************************”);对于(var i=0;i<this.length;i++){console.log(“名称:”+此[i].FirstName,此[i].LastName,“年龄:”+该[i].Age);}}//设置示例数据变量arrObj=[{名字:“Zach”,姓氏:“Emergency”,年龄:35岁},{名字:“Nancy”,姓氏:“护士”,年龄:27岁},{名字:“Ethel”,姓氏:“Emergency”,年龄:42岁},{名字:“Nina”,姓氏:“护士”,年龄:48岁},{名字:“Anthony”,姓氏:“Emergency”,年龄:44岁},{名字:“Nina”,姓氏:“护士”,年龄:32岁},{名字:“Ed”,姓氏:“Emergency”,年龄:28岁},{名字:“Peter”,姓氏:“医生”,年龄:58岁},{名字:“Al”,姓氏:“Emergency”,年龄:51岁},{名字:“Ruth”,姓氏:“注册”,年龄:62岁},{名字:“Ed”,姓氏:“Emergency”,年龄:38岁},{名字:“Tammy”,姓氏:“Triage”,年龄:29岁},{名字:“Alan”,姓氏:“Emergency”,年龄:60岁},{名字:“Nina”,姓氏:“护士”,年龄:54岁}];//单元测试arrObj.sortBy(“姓氏”).print(“姓氏升序”);arrObj.sortBy(“-姓氏”).print(“姓氏降序”);arrObj.sortBy(“姓氏”、“名字”、“年龄”).print(“姓氏升序、名字升序、年龄降序”);arrObj.sortBy(“-FirstName”,“Age”).print(“FirstName降序,Age升序”);arrObj.sortBy(“-Age”).print(“Age Descending”);