我有一个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中查看完整的脚本。

下划线.js

使用Undercore.js]。它很小,非常棒。。。

sortBy_.sortBy(列表,迭代器,[context])返回列表,按运行每个值的结果升序排列通过迭代器。迭代器也可以是属性的字符串名称按(例如长度)排序。

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

var sortedObjs = _.sortBy(objs, 'first_nom');

这是我的看法:

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

let propName = 'last_nom';

let sorted_obj = objs.sort((a,b) => {
    if(a[propName] > b[propName]) {
        return 1;
    }
    if (a[propName] < b[propName]) {
        return -1;
    }
    return 0;
}

//This works because the js built-in sort function allows us to define our
//own way of sorting, this funny looking function is simply telling `sort` how to
//determine what is larger. 
//We can use `if(a[propName] > b[propName])` because string comparison is already built into JS
//if you try console.log('a' > 'z' ? 'a' : 'z')
//the output will be 'z' as 'a' is not greater than 'z'
//The return values 0,-1,1 are how we tell JS what to sort on. We're sorting on the last_nom property of the object. 
//When sorting a list it comes down to comparing two items and how to determine which one of them is "larger". 
//We need a way to tell JS how to determine which one is larger. 
//The sort defining function will use the case that returns a 1 to mean that a > b
//and the case that returns -1 to mean that a < b

这里有很多好的答案,但我想指出,它们可以非常简单地扩展,以实现更复杂的排序。您必须做的唯一一件事就是使用OR运算符来链接比较函数,如下所示:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

其中fn1,fn2。。。是返回[-1,0,1]的排序函数。这导致“按fn1排序”和“按fn2排序”,这在SQL中相当于ORDERBY。

此解决方案基于||运算符的行为,该运算符的求值结果为第一个可转换为true的求值表达式。

最简单的表单只有一个这样的内联函数:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

使用last_nom和first_nom排序顺序有两个步骤,如下所示:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) ||
                  a.first_nom.localeCompare(b.first_nom)  )

通用比较函数可以是这样的:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

此函数可以扩展为支持数字字段、区分大小写、任意数据类型等。

您可以通过按排序优先级链接它们来使用它们:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )

这里的重点是,采用函数方法的纯JavaScript可以在没有外部库或复杂代码的情况下走很长的路。它也非常有效,因为不需要进行字符串解析。