根据JavaScript中的字符串属性值对对象数组进行排序

时间:2022-06-11 16:00:19

I have an array of JavaScript objects:

我有一个JavaScript对象数组:

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

How can I sort them by the value of last_nom in JavaScript?

如何根据JavaScript中的last_nom的值对它们进行排序?

I know about sort(a,b), but that only seems to work on strings and numbers. Do I need to add a toString method to my objects?

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

36 个解决方案

#1


2632  

It's easy enough to write your own comparison function:

很容易写出你自己的比较函数:

function compare(a,b) {
  if (a.last_nom < b.last_nom)
    return -1;
  if (a.last_nom > b.last_nom)
    return 1;
  return 0;
}

objs.sort(compare);

Or inline (c/o Marco Demaio):

或内联(c/o Marco Demaio):

objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} ); 

#2


635  

You can also create a dynamic sort function that sorts objects by their value that you pass:

您还可以创建一个动态排序函数,根据传递的对象的值对其进行排序:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

So you can have an array of objects like this:

你可以有一个这样的对象数组

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

...and it will work when you do:

…当你这样做的时候,它就会起作用:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.

实际上这已经回答了这个问题。下面的部分是写的,因为很多人联系我,抱怨它不能使用多个参数。

Multiple Parameters

You can use the function below to generate sort functions with multiple sort parameters.

您可以使用下面的函数来生成具有多个排序参数的排序函数。

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

Which would enable you to do something like this:

这样你就可以做这样的事情:

People.sort(dynamicSortMultiple("Name", "-Surname"));

Adding It To The Prototype

(Implementation which is just below is inspired from Mike R's answer)

(下面的实现灵感来自Mike R的回答)

I wouldn't recommend changing a native object prototype but just to give an example so you can implement it on your own objects (For the environments that support it, you can also use Object.defineProperty as shown in the next section, which at least doesn't have the negative side-effect of being enumerable, as described at the last part)

我不建议改变一个本地对象原型只是举一个例子,这样你就可以实现它自己的对象(环境支持,您也可以使用Object.defineProperty下一节所示,至少没有负面的副作用可列举的,在最后一部分描述)

Prototype implementation would be something like the following (Here's a working example):

原型实现类似如下(这里是一个工作示例):

//Don't just copy-paste this code. You will break the "for-in" loops
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Array.prototype.sortBy = function() {
        return this.sort(_dynamicSortMultiple.apply(null, arguments));
    }
}();

The "OK" Way Of Adding It To The Prototype

If you're targeting IE v9.0 and up then, as I previously mentioned, use Object.defineProperty like this (working example):

如果你的目标是IE v9.0,那么就像我前面提到的那样,使用Object.defineProperty(工作示例):

//Won't work below IE9, but totally safe otherwise
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Object.defineProperty(Array.prototype, "sortBy", {
        enumerable: false,
        writable: true,
        value: function() {
            return this.sort(_dynamicSortMultiple.apply(null, arguments));
        }
    });
}();

This can be an acceptable compromise until the bind operator arrives.

在绑定操作符到达之前,这是可以接受的折衷方案。

All those prototype fun enables this:

所有这些原型乐趣使这:

People.sortBy("Name", "-Surname");

You Should Read This

If you use the direct prototype access method (Object.defineProperty is fine) and other code does not check hasOwnProperty, kittens die! Ok, to be honest, no harm comes to any kitten really but probably things will break and every other developer in your team will hate you:

如果您使用直接原型访问方法(Object.defineProperty是好的)和其他代码不检查hasOwnProperty,小猫会死!好吧,老实说,对任何小猫都没有伤害,但是事情可能会破裂,你团队中的其他开发人员会恨你:

根据JavaScript中的字符串属性值对对象数组进行排序

See that last "SortBy"? Yeah. Not cool. Use Object.defineProperty where you can, and leave the Array.prototype alone otherwise.

看到最后一个“SortBy”吗?是的。不酷。可以使用Object.defineProperty,并保留数组。原型本身。

#3


150  

underscore.js

underscore.js

use underscore, its small and awesome...

使用下划线,它的小而棒…

sortBy_.sortBy(list, iterator, [context]) Returns a sorted copy of list, ranked in ascending order by the results of running each value through iterator. Iterator may also be the string name of the property to sort by (eg. length).

sortBy_。sortBy(list、iterator、[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' );

#4


137  

Don't get why people make it so complicated:

不要理解为什么人们会把事情弄得这么复杂:

objs.sort(function(a, b){
  return a.last_nom > b.last_nom;
});

For stricter engines:

更严格的引擎:

objs.sort(function(a, b){
  return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});

Swap the operator to have it sorted by reverse alphabetical order.

交换操作符,使其按字母顺序倒序排序。

#5


124  

In ES6/ES2015 or later you can do this way:

在ES6/ES2015或以后你可以这样做:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

#6


50  

If you have duplicate last names you might sort those by first name-

如果你有重复的姓氏,你可以按名字排序-

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
});

#7


36  

Simple and quick solution to this problem using prototype inheritance:

使用原型继承简单快速地解决这个问题:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

Example / Usage

例子/使用

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

Update: No longer modifies original array.

更新:不再修改原始数组。

#8


23  

Instead of using a custom comparison function, you could also create an object type with custom toString() method (which is invoked by the default comparison function):

您还可以使用定制的toString()方法(由默认的比较函数调用)来创建对象类型,而不是使用自定义的比较函数。

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

#9


14  

There are many good answers here, but I would like to point out that they can be extended very simply to achieve a lot more complex sorting. The only thing you have to do is to use the OR operator to chain comparision functions like this:

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

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

Where fn1, fn2, ... are the sort functions which return [-1,0,1]. This results in "sorting by fn1", "sorting by fn2" which is pretty much equal to ORDER BY in SQL.

fn1,fn2……是返回[-1,0,1]的排序函数。这导致了“按fn1排序”、“按fn2排序”,这在SQL中几乎等同于按by排序。

This solution is based on the behaviour of || operator which evaluates to the first evaluated expression which can be converted to true.

该解决方案基于||运算符的行为,该运算符计算第一个可被转换为true的表达式。

The simplest form has only one inlined function like this:

最简单的形式只有一个内联函数:

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

Having two steps with last_nom,first_nom sort order would look like this:

使用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)  )

A generic comparision function could be something like this:

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

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

This function could be extended to support numeric fields, case sensitity, arbitary datatypes etc.

该函数可以扩展到支持数字域、案例敏感性、仲裁数据类型等。

You can them use it with chaining them by sort priority:

你可以用它把它们按排序优先顺序链接起来:

// 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") )

The point here is that pure JavaScript with functional approach can take you a long way without external libraries or complex code. It is also very effective, since no string parsing have to be done

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

#10


13  

I know this question is too old, but I didn't see any implementation similar to mine.
This version is based on the Schwartzian transform idiom.

我知道这个问题太老了,但是我没有看到任何类似于我的实现。这个版本基于Schwartzian转换习语。

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Here's an example how to use it:

这里有一个如何使用它的例子:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

#11


13  

Lodash.js (superset of Underscore.js)

Lodash。js(Underscore.js超集)

It's good not to add a framework for every simple piece of logic, but relying on a well tested utility frameworks, speed up development and reduce the amount of bugs written is no shame.

最好不要为每一个简单的逻辑添加一个框架,但是依赖于一个经过良好测试的实用框架,加速开发并减少编写的错误并不可耻。

Lodash produces very clean code and promotes a more functional programming style, which results in less bugs. In one glimpse it becomes clear what the intent if the code is.

Lodash产生了非常干净的代码,并提倡一种功能更强的编程风格,从而减少了bug。在一瞥中,如果代码是什么,它就变得很清楚了。

OP's issue can simply be solved as:

OP的问题可以简单地解决为:

const sortedObjs = _.sortBy(objs, 'last_nom');

More info? E.g. we have following nested object:

更多的信息吗?例如,我们有以下嵌套对象:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

We now can use the _.property shorthand user.age to specify the path to the property that should be matched. We will sort the user objects by the nested age property. Yes, it allows for nested property matching!

我们现在可以用_。用户属性速记。年龄来指定应该匹配的属性的路径。我们将根据嵌套的age属性对用户对象进行排序。是的,它允许嵌套属性匹配!

const sortedObjs = _.sortBy(users, ['user.age']);

Want it reversed? No problem. Use _.reverse.

想要逆转?没有问题。使用_.reverse。

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Want to combine both using Chaining instead?

想要将两者结合使用链接?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();

#12


12  

Example Usage:

使用示例:

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

Script:

脚本:

/**
 * @description 
 * Returns a function which will sort an
 * array of objects by the given key.
 * 
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}     
 */
function 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.
  var 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.
  var moveLarger = reverse ? -1 : 1;

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

}

#13


12  

Sorting (more) Complex Arrays of Objects

Since you probably encounter more complex data structures like this array, I would expand the solution.

由于您可能会遇到更复杂的数据结构,比如这个数组,所以我将扩展解决方案。

TL;DR

Are more pluggable version based on @ege-Özcan's very lovely answer.

是基于@ege-Ozcan非常可爱的答案的可插入版本。

Problem

I encountered the below and couldn't change it. I also did not want to flatten the object temporarily. Nor did I want to use underscore / lodash, mainly for performance reasons and the fun to implement it myself.

我遇到了下面的问题,无法改变它。我也不想把物体暂时弄平。我也不想使用下划线/ lodash,主要是出于性能原因和我自己实现它的乐趣。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

Goal

The goal is to sort it primarily by People.Name.name and secondarily by People.Name.surname

我们的目标是主要按人名、姓名、人名、姓氏排序

Obstacles

Now, in the base solution uses bracket notation to compute the properties to sort for dynamically. Here, though, we would have to construct the bracket notation dynamically also, since you would expect some like People['Name.name'] would work - which doesn't.

现在,在基本解决方案中,使用括号表示法来计算要动态排序的属性。不过,在这里,我们也必须动态地构造方括号表示法,因为您可能会认为像People ('Name.name')这样的符号可以工作,但实际上不行。

Simply doing People['Name']['name'], on the other hand, is static and only allows you to go down the n-th level.

另一方面,简单地执行人名['Name'][' Name']是静态的,只允许您执行第n个级别。

Solution

The main addition here will be to walk down the object tree and determine the value of the last leaf, you have to specify, as well as any intermediary leaf.

这里的主要添加内容是沿着对象树并确定最后一个叶的值,您必须指定,以及任何中间叶。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://*.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

Example

Working example on JSBin

在JSBin工作示例

#14


11  

I have a piece of code that works for me:

我有一个适合我的代码:

arr.sort((a, b) => a.name > b.name)

UPDATE: Not working always, so it is not correct :(

更新:不总是工作,所以不正确

#15


9  

A simple way:

一个简单的方法:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});

See that '.toLowerCase()' is necessary to prevent erros in comparing strings.

请注意,“. tolowercase()”对于防止在比较字符串中出现erros是必要的。

#16


8  

Combining Ege's dynamic solution with Vinay's idea, you get a nice robust solution:

将Ege的动态解决方案与Vinay的想法结合起来,得到一个很好的解决方案:

Array.prototype.sortBy = function() {
    function _sortByAttr(attr) {
        var sortOrder = 1;
        if (attr[0] == "-") {
            sortOrder = -1;
            attr = attr.substr(1);
        }
        return function(a, b) {
            var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
            return result * sortOrder;
        }
    }
    function _getSortFunc() {
        if (arguments.length == 0) {
            throw "Zero length arguments not allowed for Array.sortBy()";
        }
        var args = arguments;
        return function(a, b) {
            for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
                result = _sortByAttr(args[i])(a, b);
            }
            return result;
        }
    }
    return this.sort(_getSortFunc.apply(null, arguments));
}

Usage:

用法:

// Utility for printing objects
Array.prototype.print = function(title) {
    console.log("************************************************************************");
    console.log("**** "+title);
    console.log("************************************************************************");
    for (var i = 0; i < this.length; i++) {
        console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
    }
}

// Setup sample data
var arrObj = [
    {FirstName: "Zach", LastName: "Emergency", Age: 35},
    {FirstName: "Nancy", LastName: "Nurse", Age: 27},
    {FirstName: "Ethel", LastName: "Emergency", Age: 42},
    {FirstName: "Nina", LastName: "Nurse", Age: 48},
    {FirstName: "Anthony", LastName: "Emergency", Age: 44},
    {FirstName: "Nina", LastName: "Nurse", Age: 32},
    {FirstName: "Ed", LastName: "Emergency", Age: 28},
    {FirstName: "Peter", LastName: "Physician", Age: 58},
    {FirstName: "Al", LastName: "Emergency", Age: 51},
    {FirstName: "Ruth", LastName: "Registration", Age: 62},
    {FirstName: "Ed", LastName: "Emergency", Age: 38},
    {FirstName: "Tammy", LastName: "Triage", Age: 29},
    {FirstName: "Alan", LastName: "Emergency", Age: 60},
    {FirstName: "Nina", LastName: "Nurse", Age: 54}
];

//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");

#17


7  

Acording your example, you need to sort by two fields (last name, first name), rather then one. You can use Alasql library to make this sort in one line:

根据示例,需要按两个字段(姓、名)排序,而不是一个字段。您可以使用Alasql库在一行中完成这类操作:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

Try this example at jsFiddle.

在jsFiddle尝试这个示例。

#18


6  

additional desc params for Ege Özcan code

额外的desc params Ege Ozcan代码

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }   
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}

#19


5  

You may need to convert them to the lower case in order to prevent from confusion.

您可能需要将它们转换为小写,以避免混淆。

objs.sort(function (a,b) {

var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase()

if (nameA < nameB)
  return -1;
if (nameA > nameB)
  return 1;
return 0;  //no sorting

})

#20


5  

objs.sort(function(a,b){return b.last_nom>a.last_nom})

#21


5  

One more option:

一个选项:

var someArray = [...];

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

someArray.sort(generateSortFn('name', true));

sorts ascending by default.

默认排序提升。

#22


4  

function compare(propName) {
    return function(a,b) {
        if (a[propName] < b[propName])
            return -1;
        if (a[propName] > b[propName])
            return 1;
        return 0;
    };
}

objs.sort(compare("last_nom"));

#23


4  

This is a simple problem, don't know why people have such complex solution.
A simple sort function (based on quick-sort algorithm):

这是一个简单的问题,不知道为什么人们会有如此复杂的解决方案。一个简单的排序函数(基于快速排序算法):

function sortObjectsArray(objectsArray, sortKey)
        {
            // Quick Sort:
            var retVal;

            if (1 < objectsArray.length)
            {
                var pivotIndex = Math.floor((objectsArray.length - 1) / 2);  // middle index
                var pivotItem = objectsArray[pivotIndex];                    // value in the middle index
                var less = [], more = [];

                objectsArray.splice(pivotIndex, 1);                          // remove the item in the pivot position
                objectsArray.forEach(function(value, index, array)
                {
                    value[sortKey] <= pivotItem[sortKey] ?                   // compare the 'sortKey' proiperty
                        less.push(value) :
                        more.push(value) ;
                });

                retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
            }
            else
            {
                retVal = objectsArray;
            }

            return retVal;
        }

Use example:

使用的例子:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');

#24


3  

I Just enhanced Ege Özcan's dynamic sort to dive deep inside objects. If Data looks like this:

我增强了Ege Ozcan的动态分类,以深入物体内部。如果数据是这样的:

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

and if you want to sort it over a.a property I think my enhancement helps very well. I add new functionality to objects like this:

如果你想对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;
    }
});

and changed _dynamicSort's return function:

改变_dynamicSort的返回函数:

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

And now you can sort by a.a. this way:

现在你可以通过a.a.来排序:

obj.sortBy('a.a');

See Commplete script in JSFiddle

请参阅JSFiddle中的Commplete脚本

#25


2  

Using xPrototype: https://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln

使用xPrototype:https://github.com/reduardo7/xPrototype/blob/master/README.md sortbycol1-col2-coln

var o = [ 
  { Name: 'Lazslo', LastName: 'Jamf'     },
  { Name: 'Pig',    LastName: 'Bodine'   },
  { Name: 'Pirate', LastName: 'Prentice' },
  { Name: 'Pag',    LastName: 'Bodine'   }
];


// Original
o.each(function (a, b) { console.log(a, b); });
/*
 0 Object {Name: "Lazslo", LastName: "Jamf"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Pirate", LastName: "Prentice"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort By LastName ASC, Name ASC
o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName ASC and Name ASC
o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName DESC and Name DESC
o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pig", LastName: "Bodine"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort by LastName DESC and Name ASC
o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pag", LastName: "Bodine"}
 3 Object {Name: "Pig", LastName: "Bodine"}
*/

#26


2  

Using Ramda,

使用Ramda,

npm install ramda

npm安装ramda

import R from 'ramda'
var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)

#27


2  

As of 2018 there is a much shorter and elegant solution. Just use. Array.prototype.sort().

到2018年,有一个更短、更优雅的解决方案。只使用。Array.prototype.sort()。

Example:

例子:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

#28


1  

I came into problem of sorting array of objects, with changing priority of values, basically I want to sort array of peoples by their Age, and then by surname - or just by surname, name. I think that this is most simple solution compared to another answers.

我遇到了排序对象数组的问题,随着优先级的变化,基本上我想按人们的年龄排序,然后按姓氏-或者只是按姓氏,名字排序。我认为这是与其他答案相比最简单的解决方案。

it' is used by calling sortPeoples(['array', 'of', 'properties'], reverse=false)

它被调用sortPeoples(['array', 'of', 'properties'],反向=false)

///////////////////////example array of peoples ///////////////////////

var peoples = [
    {name: "Zach", surname: "Emergency", age: 1},
    {name: "Nancy", surname: "Nurse", age: 1},
    {name: "Ethel", surname: "Emergency", age: 1},
    {name: "Nina", surname: "Nurse", age: 42},
    {name: "Anthony", surname: "Emergency", age: 42},
    {name: "Nina", surname: "Nurse", age: 32},
    {name: "Ed", surname: "Emergency", age: 28},
    {name: "Peter", surname: "Physician", age: 58},
    {name: "Al", surname: "Emergency", age: 58},
    {name: "Ruth", surname: "Registration", age: 62},
    {name: "Ed", surname: "Emergency", age: 38},
    {name: "Tammy", surname: "Triage", age: 29},
    {name: "Alan", surname: "Emergency", age: 60},
    {name: "Nina", surname: "Nurse", age: 58}
];



//////////////////////// Sorting function /////////////////////
function sortPeoples(propertyArr, reverse) {
        function compare(a,b) {
            var i=0;
            while (propertyArr[i]) {
                if (a[propertyArr[i]] < b[propertyArr[i]])  return -1;
                if (a[propertyArr[i]] > b[propertyArr[i]])  return 1;
                i++;
            }
            return 0;
            }
        peoples.sort(compare);
        if (reverse){
            peoples.reverse();
        }
    };

////////////////end of sorting method///////////////
function printPeoples(){
  $('#output').html('');
peoples.forEach( function(person){
 $('#output').append(person.surname+" "+person.name+" "+person.age+"<br>");
} )
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
  <html>
  <body>
<button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br>
<button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br>
<button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br>
<button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br>
        
    <div id="output"></div>
    </body>
  </html>

#29


1  

This will sort a two level nested array by the property passed to it in alpha numeric order.

这将根据以字母数字顺序传递给它的属性对两层嵌套数组进行排序。

function sortArrayObjectsByPropAlphaNum(property) {
    return function (a,b) {
        var reA = /[^a-zA-Z]/g;
        var reN = /[^0-9]/g;
        var aA = a[property].replace(reA, '');
        var bA = b[property].replace(reA, '');

        if(aA === bA) {
            var aN = parseInt(a[property].replace(reN, ''), 10);
            var bN = parseInt(b[property].replace(reN, ''), 10);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return a[property] > b[property] ? 1 : -1;
        }
    };
}

Usage:

用法:

objs.sort(utils.sortArrayObjectsByPropAlphaNum('last_nom'));

#30


1  

So here is one sorting algorithm which can sort in any order , throughout array of any kind of objects , without the restriction of datatype comparison ( i.e. Number , String )

这是一种排序算法,它可以对任意类型的对象数组进行排序,不受数据类型比较的限制(例如,数字,字符串)

function smoothSort(items,prop,reverse) {  
    var length = items.length;
    for (var i = (length - 1); i >= 0; i--) {
        //Number of passes
        for (var j = (length - i); j > 0; j--) {
            //Compare the adjacent positions
            if(reverse){
              if (items[j][prop] > items[j - 1][prop]) {
                //Swap the numbers
                var tmp = items[j];
                items[j] = items[j - 1];
                items[j - 1] = tmp;
            }
            }

            if(!reverse){
              if (items[j][prop] < items[j - 1][prop]) {
                  //Swap the numbers
                  var tmp = items[j];
                  items[j] = items[j - 1];
                  items[j - 1] = tmp;
              }
            }
        }
    }

    return items;
}
  • the first argument items is the array of objects ,

    第一个参数项是对象数组,

  • prop is the key of the object on which you want to sort ,

    prop是要排序对象的键,

  • reverse is a boolean parameter which on being true results in Ascending order and in false it returns descending order.

    反向是一个布尔参数,当为真时,它会以升序返回,反之则返回降序。

#1


2632  

It's easy enough to write your own comparison function:

很容易写出你自己的比较函数:

function compare(a,b) {
  if (a.last_nom < b.last_nom)
    return -1;
  if (a.last_nom > b.last_nom)
    return 1;
  return 0;
}

objs.sort(compare);

Or inline (c/o Marco Demaio):

或内联(c/o Marco Demaio):

objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} ); 

#2


635  

You can also create a dynamic sort function that sorts objects by their value that you pass:

您还可以创建一个动态排序函数,根据传递的对象的值对其进行排序:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

So you can have an array of objects like this:

你可以有一个这样的对象数组

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

...and it will work when you do:

…当你这样做的时候,它就会起作用:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.

实际上这已经回答了这个问题。下面的部分是写的,因为很多人联系我,抱怨它不能使用多个参数。

Multiple Parameters

You can use the function below to generate sort functions with multiple sort parameters.

您可以使用下面的函数来生成具有多个排序参数的排序函数。

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

Which would enable you to do something like this:

这样你就可以做这样的事情:

People.sort(dynamicSortMultiple("Name", "-Surname"));

Adding It To The Prototype

(Implementation which is just below is inspired from Mike R's answer)

(下面的实现灵感来自Mike R的回答)

I wouldn't recommend changing a native object prototype but just to give an example so you can implement it on your own objects (For the environments that support it, you can also use Object.defineProperty as shown in the next section, which at least doesn't have the negative side-effect of being enumerable, as described at the last part)

我不建议改变一个本地对象原型只是举一个例子,这样你就可以实现它自己的对象(环境支持,您也可以使用Object.defineProperty下一节所示,至少没有负面的副作用可列举的,在最后一部分描述)

Prototype implementation would be something like the following (Here's a working example):

原型实现类似如下(这里是一个工作示例):

//Don't just copy-paste this code. You will break the "for-in" loops
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Array.prototype.sortBy = function() {
        return this.sort(_dynamicSortMultiple.apply(null, arguments));
    }
}();

The "OK" Way Of Adding It To The Prototype

If you're targeting IE v9.0 and up then, as I previously mentioned, use Object.defineProperty like this (working example):

如果你的目标是IE v9.0,那么就像我前面提到的那样,使用Object.defineProperty(工作示例):

//Won't work below IE9, but totally safe otherwise
!function() {
    function _dynamicSortMultiple(attr) {
       /* dynamicSortMultiple function body comes here */
    }
    function _dynamicSort(property) {
        /* dynamicSort function body comes here */
    }
    Object.defineProperty(Array.prototype, "sortBy", {
        enumerable: false,
        writable: true,
        value: function() {
            return this.sort(_dynamicSortMultiple.apply(null, arguments));
        }
    });
}();

This can be an acceptable compromise until the bind operator arrives.

在绑定操作符到达之前,这是可以接受的折衷方案。

All those prototype fun enables this:

所有这些原型乐趣使这:

People.sortBy("Name", "-Surname");

You Should Read This

If you use the direct prototype access method (Object.defineProperty is fine) and other code does not check hasOwnProperty, kittens die! Ok, to be honest, no harm comes to any kitten really but probably things will break and every other developer in your team will hate you:

如果您使用直接原型访问方法(Object.defineProperty是好的)和其他代码不检查hasOwnProperty,小猫会死!好吧,老实说,对任何小猫都没有伤害,但是事情可能会破裂,你团队中的其他开发人员会恨你:

根据JavaScript中的字符串属性值对对象数组进行排序

See that last "SortBy"? Yeah. Not cool. Use Object.defineProperty where you can, and leave the Array.prototype alone otherwise.

看到最后一个“SortBy”吗?是的。不酷。可以使用Object.defineProperty,并保留数组。原型本身。

#3


150  

underscore.js

underscore.js

use underscore, its small and awesome...

使用下划线,它的小而棒…

sortBy_.sortBy(list, iterator, [context]) Returns a sorted copy of list, ranked in ascending order by the results of running each value through iterator. Iterator may also be the string name of the property to sort by (eg. length).

sortBy_。sortBy(list、iterator、[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' );

#4


137  

Don't get why people make it so complicated:

不要理解为什么人们会把事情弄得这么复杂:

objs.sort(function(a, b){
  return a.last_nom > b.last_nom;
});

For stricter engines:

更严格的引擎:

objs.sort(function(a, b){
  return a.last_nom == b.last_nom ? 0 : +(a.last_nom > b.last_nom) || -1;
});

Swap the operator to have it sorted by reverse alphabetical order.

交换操作符,使其按字母顺序倒序排序。

#5


124  

In ES6/ES2015 or later you can do this way:

在ES6/ES2015或以后你可以这样做:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

#6


50  

If you have duplicate last names you might sort those by first name-

如果你有重复的姓氏,你可以按名字排序-

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
});

#7


36  

Simple and quick solution to this problem using prototype inheritance:

使用原型继承简单快速地解决这个问题:

Array.prototype.sortBy = function(p) {
  return this.slice(0).sort(function(a,b) {
    return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
  });
}

Example / Usage

例子/使用

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortBy('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortBy('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]

Update: No longer modifies original array.

更新:不再修改原始数组。

#8


23  

Instead of using a custom comparison function, you could also create an object type with custom toString() method (which is invoked by the default comparison function):

您还可以使用定制的toString()方法(由默认的比较函数调用)来创建对象类型,而不是使用自定义的比较函数。

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();

#9


14  

There are many good answers here, but I would like to point out that they can be extended very simply to achieve a lot more complex sorting. The only thing you have to do is to use the OR operator to chain comparision functions like this:

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

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

Where fn1, fn2, ... are the sort functions which return [-1,0,1]. This results in "sorting by fn1", "sorting by fn2" which is pretty much equal to ORDER BY in SQL.

fn1,fn2……是返回[-1,0,1]的排序函数。这导致了“按fn1排序”、“按fn2排序”,这在SQL中几乎等同于按by排序。

This solution is based on the behaviour of || operator which evaluates to the first evaluated expression which can be converted to true.

该解决方案基于||运算符的行为,该运算符计算第一个可被转换为true的表达式。

The simplest form has only one inlined function like this:

最简单的形式只有一个内联函数:

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

Having two steps with last_nom,first_nom sort order would look like this:

使用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)  )

A generic comparision function could be something like this:

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

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

This function could be extended to support numeric fields, case sensitity, arbitary datatypes etc.

该函数可以扩展到支持数字域、案例敏感性、仲裁数据类型等。

You can them use it with chaining them by sort priority:

你可以用它把它们按排序优先顺序链接起来:

// 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") )

The point here is that pure JavaScript with functional approach can take you a long way without external libraries or complex code. It is also very effective, since no string parsing have to be done

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

#10


13  

I know this question is too old, but I didn't see any implementation similar to mine.
This version is based on the Schwartzian transform idiom.

我知道这个问题太老了,但是我没有看到任何类似于我的实现。这个版本基于Schwartzian转换习语。

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Here's an example how to use it:

这里有一个如何使用它的例子:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

#11


13  

Lodash.js (superset of Underscore.js)

Lodash。js(Underscore.js超集)

It's good not to add a framework for every simple piece of logic, but relying on a well tested utility frameworks, speed up development and reduce the amount of bugs written is no shame.

最好不要为每一个简单的逻辑添加一个框架,但是依赖于一个经过良好测试的实用框架,加速开发并减少编写的错误并不可耻。

Lodash produces very clean code and promotes a more functional programming style, which results in less bugs. In one glimpse it becomes clear what the intent if the code is.

Lodash产生了非常干净的代码,并提倡一种功能更强的编程风格,从而减少了bug。在一瞥中,如果代码是什么,它就变得很清楚了。

OP's issue can simply be solved as:

OP的问题可以简单地解决为:

const sortedObjs = _.sortBy(objs, 'last_nom');

More info? E.g. we have following nested object:

更多的信息吗?例如,我们有以下嵌套对象:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

We now can use the _.property shorthand user.age to specify the path to the property that should be matched. We will sort the user objects by the nested age property. Yes, it allows for nested property matching!

我们现在可以用_。用户属性速记。年龄来指定应该匹配的属性的路径。我们将根据嵌套的age属性对用户对象进行排序。是的,它允许嵌套属性匹配!

const sortedObjs = _.sortBy(users, ['user.age']);

Want it reversed? No problem. Use _.reverse.

想要逆转?没有问题。使用_.reverse。

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Want to combine both using Chaining instead?

想要将两者结合使用链接?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();

#12


12  

Example Usage:

使用示例:

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

Script:

脚本:

/**
 * @description 
 * Returns a function which will sort an
 * array of objects by the given key.
 * 
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}     
 */
function 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.
  var 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.
  var moveLarger = reverse ? -1 : 1;

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

}

#13


12  

Sorting (more) Complex Arrays of Objects

Since you probably encounter more complex data structures like this array, I would expand the solution.

由于您可能会遇到更复杂的数据结构,比如这个数组,所以我将扩展解决方案。

TL;DR

Are more pluggable version based on @ege-Özcan's very lovely answer.

是基于@ege-Ozcan非常可爱的答案的可插入版本。

Problem

I encountered the below and couldn't change it. I also did not want to flatten the object temporarily. Nor did I want to use underscore / lodash, mainly for performance reasons and the fun to implement it myself.

我遇到了下面的问题,无法改变它。我也不想把物体暂时弄平。我也不想使用下划线/ lodash,主要是出于性能原因和我自己实现它的乐趣。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

Goal

The goal is to sort it primarily by People.Name.name and secondarily by People.Name.surname

我们的目标是主要按人名、姓名、人名、姓氏排序

Obstacles

Now, in the base solution uses bracket notation to compute the properties to sort for dynamically. Here, though, we would have to construct the bracket notation dynamically also, since you would expect some like People['Name.name'] would work - which doesn't.

现在,在基本解决方案中,使用括号表示法来计算要动态排序的属性。不过,在这里,我们也必须动态地构造方括号表示法,因为您可能会认为像People ('Name.name')这样的符号可以工作,但实际上不行。

Simply doing People['Name']['name'], on the other hand, is static and only allows you to go down the n-th level.

另一方面,简单地执行人名['Name'][' Name']是静态的,只允许您执行第n个级别。

Solution

The main addition here will be to walk down the object tree and determine the value of the last leaf, you have to specify, as well as any intermediary leaf.

这里的主要添加内容是沿着对象树并确定最后一个叶的值,您必须指定,以及任何中间叶。

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://*.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

Example

Working example on JSBin

在JSBin工作示例

#14


11  

I have a piece of code that works for me:

我有一个适合我的代码:

arr.sort((a, b) => a.name > b.name)

UPDATE: Not working always, so it is not correct :(

更新:不总是工作,所以不正确

#15


9  

A simple way:

一个简单的方法:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});

See that '.toLowerCase()' is necessary to prevent erros in comparing strings.

请注意,“. tolowercase()”对于防止在比较字符串中出现erros是必要的。

#16


8  

Combining Ege's dynamic solution with Vinay's idea, you get a nice robust solution:

将Ege的动态解决方案与Vinay的想法结合起来,得到一个很好的解决方案:

Array.prototype.sortBy = function() {
    function _sortByAttr(attr) {
        var sortOrder = 1;
        if (attr[0] == "-") {
            sortOrder = -1;
            attr = attr.substr(1);
        }
        return function(a, b) {
            var result = (a[attr] < b[attr]) ? -1 : (a[attr] > b[attr]) ? 1 : 0;
            return result * sortOrder;
        }
    }
    function _getSortFunc() {
        if (arguments.length == 0) {
            throw "Zero length arguments not allowed for Array.sortBy()";
        }
        var args = arguments;
        return function(a, b) {
            for (var result = 0, i = 0; result == 0 && i < args.length; i++) {
                result = _sortByAttr(args[i])(a, b);
            }
            return result;
        }
    }
    return this.sort(_getSortFunc.apply(null, arguments));
}

Usage:

用法:

// Utility for printing objects
Array.prototype.print = function(title) {
    console.log("************************************************************************");
    console.log("**** "+title);
    console.log("************************************************************************");
    for (var i = 0; i < this.length; i++) {
        console.log("Name: "+this[i].FirstName, this[i].LastName, "Age: "+this[i].Age);
    }
}

// Setup sample data
var arrObj = [
    {FirstName: "Zach", LastName: "Emergency", Age: 35},
    {FirstName: "Nancy", LastName: "Nurse", Age: 27},
    {FirstName: "Ethel", LastName: "Emergency", Age: 42},
    {FirstName: "Nina", LastName: "Nurse", Age: 48},
    {FirstName: "Anthony", LastName: "Emergency", Age: 44},
    {FirstName: "Nina", LastName: "Nurse", Age: 32},
    {FirstName: "Ed", LastName: "Emergency", Age: 28},
    {FirstName: "Peter", LastName: "Physician", Age: 58},
    {FirstName: "Al", LastName: "Emergency", Age: 51},
    {FirstName: "Ruth", LastName: "Registration", Age: 62},
    {FirstName: "Ed", LastName: "Emergency", Age: 38},
    {FirstName: "Tammy", LastName: "Triage", Age: 29},
    {FirstName: "Alan", LastName: "Emergency", Age: 60},
    {FirstName: "Nina", LastName: "Nurse", Age: 54}
];

//Unit Tests
arrObj.sortBy("LastName").print("LastName Ascending");
arrObj.sortBy("-LastName").print("LastName Descending");
arrObj.sortBy("LastName", "FirstName", "-Age").print("LastName Ascending, FirstName Ascending, Age Descending");
arrObj.sortBy("-FirstName", "Age").print("FirstName Descending, Age Ascending");
arrObj.sortBy("-Age").print("Age Descending");

#17


7  

Acording your example, you need to sort by two fields (last name, first name), rather then one. You can use Alasql library to make this sort in one line:

根据示例,需要按两个字段(姓、名)排序,而不是一个字段。您可以使用Alasql库在一行中完成这类操作:

var res = alasql('SELECT * FROM ? ORDER BY last_nom, first_nom',[objs]);

Try this example at jsFiddle.

在jsFiddle尝试这个示例。

#18


6  

additional desc params for Ege Özcan code

额外的desc params Ege Ozcan代码

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }   
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}

#19


5  

You may need to convert them to the lower case in order to prevent from confusion.

您可能需要将它们转换为小写,以避免混淆。

objs.sort(function (a,b) {

var nameA=a.last_nom.toLowerCase(), nameB=b.last_nom.toLowerCase()

if (nameA < nameB)
  return -1;
if (nameA > nameB)
  return 1;
return 0;  //no sorting

})

#20


5  

objs.sort(function(a,b){return b.last_nom>a.last_nom})

#21


5  

One more option:

一个选项:

var someArray = [...];

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

someArray.sort(generateSortFn('name', true));

sorts ascending by default.

默认排序提升。

#22


4  

function compare(propName) {
    return function(a,b) {
        if (a[propName] < b[propName])
            return -1;
        if (a[propName] > b[propName])
            return 1;
        return 0;
    };
}

objs.sort(compare("last_nom"));

#23


4  

This is a simple problem, don't know why people have such complex solution.
A simple sort function (based on quick-sort algorithm):

这是一个简单的问题,不知道为什么人们会有如此复杂的解决方案。一个简单的排序函数(基于快速排序算法):

function sortObjectsArray(objectsArray, sortKey)
        {
            // Quick Sort:
            var retVal;

            if (1 < objectsArray.length)
            {
                var pivotIndex = Math.floor((objectsArray.length - 1) / 2);  // middle index
                var pivotItem = objectsArray[pivotIndex];                    // value in the middle index
                var less = [], more = [];

                objectsArray.splice(pivotIndex, 1);                          // remove the item in the pivot position
                objectsArray.forEach(function(value, index, array)
                {
                    value[sortKey] <= pivotItem[sortKey] ?                   // compare the 'sortKey' proiperty
                        less.push(value) :
                        more.push(value) ;
                });

                retVal = sortObjectsArray(less, sortKey).concat([pivotItem], sortObjectsArray(more, sortKey));
            }
            else
            {
                retVal = objectsArray;
            }

            return retVal;
        }

Use example:

使用的例子:

var myArr = 
        [
            { val: 'x', idx: 3 },
            { val: 'y', idx: 2 },
            { val: 'z', idx: 5 },
        ];
myArr = sortObjectsArray(myArr, 'idx');

#24


3  

I Just enhanced Ege Özcan's dynamic sort to dive deep inside objects. If Data looks like this:

我增强了Ege Ozcan的动态分类,以深入物体内部。如果数据是这样的:

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

and if you want to sort it over a.a property I think my enhancement helps very well. I add new functionality to objects like this:

如果你想对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;
    }
});

and changed _dynamicSort's return function:

改变_dynamicSort的返回函数:

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

And now you can sort by a.a. this way:

现在你可以通过a.a.来排序:

obj.sortBy('a.a');

See Commplete script in JSFiddle

请参阅JSFiddle中的Commplete脚本

#25


2  

Using xPrototype: https://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln

使用xPrototype:https://github.com/reduardo7/xPrototype/blob/master/README.md sortbycol1-col2-coln

var o = [ 
  { Name: 'Lazslo', LastName: 'Jamf'     },
  { Name: 'Pig',    LastName: 'Bodine'   },
  { Name: 'Pirate', LastName: 'Prentice' },
  { Name: 'Pag',    LastName: 'Bodine'   }
];


// Original
o.each(function (a, b) { console.log(a, b); });
/*
 0 Object {Name: "Lazslo", LastName: "Jamf"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Pirate", LastName: "Prentice"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort By LastName ASC, Name ASC
o.sortBy('LastName', 'Name').each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName ASC and Name ASC
o.sortBy('LastName'.asc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pag", LastName: "Bodine"}
 1 Object {Name: "Pig", LastName: "Bodine"}
 2 Object {Name: "Lazslo", LastName: "Jamf"}
 3 Object {Name: "Pirate", LastName: "Prentice"}
*/


// Sort by LastName DESC and Name DESC
o.sortBy('LastName'.desc, 'Name'.desc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pig", LastName: "Bodine"}
 3 Object {Name: "Pag", LastName: "Bodine"}
*/


// Sort by LastName DESC and Name ASC
o.sortBy('LastName'.desc, 'Name'.asc).each(function(a, b) { console.log(a, b); });
/*
 0 Object {Name: "Pirate", LastName: "Prentice"}
 1 Object {Name: "Lazslo", LastName: "Jamf"}
 2 Object {Name: "Pag", LastName: "Bodine"}
 3 Object {Name: "Pig", LastName: "Bodine"}
*/

#26


2  

Using Ramda,

使用Ramda,

npm install ramda

npm安装ramda

import R from 'ramda'
var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)

#27


2  

As of 2018 there is a much shorter and elegant solution. Just use. Array.prototype.sort().

到2018年,有一个更短、更优雅的解决方案。只使用。Array.prototype.sort()。

Example:

例子:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

#28


1  

I came into problem of sorting array of objects, with changing priority of values, basically I want to sort array of peoples by their Age, and then by surname - or just by surname, name. I think that this is most simple solution compared to another answers.

我遇到了排序对象数组的问题,随着优先级的变化,基本上我想按人们的年龄排序,然后按姓氏-或者只是按姓氏,名字排序。我认为这是与其他答案相比最简单的解决方案。

it' is used by calling sortPeoples(['array', 'of', 'properties'], reverse=false)

它被调用sortPeoples(['array', 'of', 'properties'],反向=false)

///////////////////////example array of peoples ///////////////////////

var peoples = [
    {name: "Zach", surname: "Emergency", age: 1},
    {name: "Nancy", surname: "Nurse", age: 1},
    {name: "Ethel", surname: "Emergency", age: 1},
    {name: "Nina", surname: "Nurse", age: 42},
    {name: "Anthony", surname: "Emergency", age: 42},
    {name: "Nina", surname: "Nurse", age: 32},
    {name: "Ed", surname: "Emergency", age: 28},
    {name: "Peter", surname: "Physician", age: 58},
    {name: "Al", surname: "Emergency", age: 58},
    {name: "Ruth", surname: "Registration", age: 62},
    {name: "Ed", surname: "Emergency", age: 38},
    {name: "Tammy", surname: "Triage", age: 29},
    {name: "Alan", surname: "Emergency", age: 60},
    {name: "Nina", surname: "Nurse", age: 58}
];



//////////////////////// Sorting function /////////////////////
function sortPeoples(propertyArr, reverse) {
        function compare(a,b) {
            var i=0;
            while (propertyArr[i]) {
                if (a[propertyArr[i]] < b[propertyArr[i]])  return -1;
                if (a[propertyArr[i]] > b[propertyArr[i]])  return 1;
                i++;
            }
            return 0;
            }
        peoples.sort(compare);
        if (reverse){
            peoples.reverse();
        }
    };

////////////////end of sorting method///////////////
function printPeoples(){
  $('#output').html('');
peoples.forEach( function(person){
 $('#output').append(person.surname+" "+person.name+" "+person.age+"<br>");
} )
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
  <html>
  <body>
<button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br>
<button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br>
<button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br>
<button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br>
        
    <div id="output"></div>
    </body>
  </html>

#29


1  

This will sort a two level nested array by the property passed to it in alpha numeric order.

这将根据以字母数字顺序传递给它的属性对两层嵌套数组进行排序。

function sortArrayObjectsByPropAlphaNum(property) {
    return function (a,b) {
        var reA = /[^a-zA-Z]/g;
        var reN = /[^0-9]/g;
        var aA = a[property].replace(reA, '');
        var bA = b[property].replace(reA, '');

        if(aA === bA) {
            var aN = parseInt(a[property].replace(reN, ''), 10);
            var bN = parseInt(b[property].replace(reN, ''), 10);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return a[property] > b[property] ? 1 : -1;
        }
    };
}

Usage:

用法:

objs.sort(utils.sortArrayObjectsByPropAlphaNum('last_nom'));

#30


1  

So here is one sorting algorithm which can sort in any order , throughout array of any kind of objects , without the restriction of datatype comparison ( i.e. Number , String )

这是一种排序算法,它可以对任意类型的对象数组进行排序,不受数据类型比较的限制(例如,数字,字符串)

function smoothSort(items,prop,reverse) {  
    var length = items.length;
    for (var i = (length - 1); i >= 0; i--) {
        //Number of passes
        for (var j = (length - i); j > 0; j--) {
            //Compare the adjacent positions
            if(reverse){
              if (items[j][prop] > items[j - 1][prop]) {
                //Swap the numbers
                var tmp = items[j];
                items[j] = items[j - 1];
                items[j - 1] = tmp;
            }
            }

            if(!reverse){
              if (items[j][prop] < items[j - 1][prop]) {
                  //Swap the numbers
                  var tmp = items[j];
                  items[j] = items[j - 1];
                  items[j - 1] = tmp;
              }
            }
        }
    }

    return items;
}
  • the first argument items is the array of objects ,

    第一个参数项是对象数组,

  • prop is the key of the object on which you want to sort ,

    prop是要排序对象的键,

  • reverse is a boolean parameter which on being true results in Ascending order and in false it returns descending order.

    反向是一个布尔参数,当为真时,它会以升序返回,反之则返回降序。