简体   繁体   English

按字符串属性值对对象数组进行排序

[英]Sort array of objects by string property value

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.我知道sort(a,b) ,但这似乎只适用于字符串和数字。 Do I need to add a toString() method to my objects?我需要向我的对象添加toString()方法吗?

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((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0))

Or simplified for numeric (c/o Andre Figueiredo):或简化为数字(c/o Andre Figueiredo):

objs.sort((a,b) => a.last_nom - b.last_nom); // b - a for reverse sort

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) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs
         */
        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"));

Subclassing Array子类化数组

For the lucky among us who can use ES6, which allows extending the native objects:对于我们当中可以使用 ES6 的幸运儿,它允许扩展原生对象:

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple(...args));
    }
}

That would enable this:这将实现这一点:

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

In ES6/ES2015 or later you can do this way:在 ES6/ES2015 或更高版本中,您可以这样做:

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

Prior to ES6/ES2015在 ES6/ES2015 之前

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

underscore.js下划线.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. sortBy_.sortBy(list, iterator, [context]) 返回列表的排序副本,按通过迭代器运行每个值的结果按升序排列。 Iterator may also be the string name of the property to sort by (eg. length).迭代器也可以是要排序的属性的字符串名称(例如长度)。

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

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. 交换运算符以按相反的字母顺序对其进行排序。

Case sensitive区分大小写

arr.sort((a, b) => a.name > b.name ? 1 : -1);

Case Insensitive不区分大小写

arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);

Useful Note有用的说明

If no change in order (in case of the same strings) then the condition > will fail and -1 will be returned.如果顺序没有变化(在相同字符串的情况下),则条件>将失败并返回-1 But if strings are same then returning 1 or -1 will result in correct output但是如果字符串相同,则返回 1 或 -1 将导致正确的输出

The other option could be to use >= operator instead of >另一种选择可能是使用>=运算符而不是>


 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; // Define a couple of sorting callback functions, one with hardcoded sort key and the other with an argument sort key const sorter1 = (a, b) => a.last_nom.toLowerCase() > b.last_nom.toLowerCase() ? 1 : -1; const sorter2 = (sortBy) => (a, b) => a[sortBy].toLowerCase() > b[sortBy].toLowerCase() ? 1 : -1; objs.sort(sorter1); console.log("Using sorter1 - Hardcoded sort property last_name", objs); objs.sort(sorter2('first_nom')); console.log("Using sorter2 - passed param sortBy='first_nom'", objs); objs.sort(sorter2('last_nom')); console.log("Using sorter2 - passed param sortBy='last_nom'", objs);

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

As of 2018 there is a much shorter and elegant solution.截至 2018 年,有一个更短更优雅的解决方案。 Just use.就用吧。 Array.prototype.sort() . 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;
});

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.更新:不再修改原始数组。

Old answer that is not correct:不正确的旧答案:

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

UPDATE更新

From Beauchamp's comment:来自 Beauchamp 的评论:

arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

More readable format:更易读的格式:

arr.sort((a, b) => {
  if (a.name < b.name) return -1
  return a.name > b.name ? 1 : 0
})

Without nested ternaries:没有嵌套三元组:

arr.sort((a, b) => a.name < b.name ? - 1 : Number(a.name > b.name))

Explanation: Number() will cast true to 1 and false to 0 .说明: Number()会将true转换为1并将false转换为0

Lodash.js (superset of Underscore.js ) Lodash.jsUnderscore.js的超集)

It's good not to add a framework for every simple piece of logic, but relying on well tested utility frameworks can speed up development and reduce the amount of bugs.最好不要为每个简单的逻辑添加框架,但是依靠经过良好测试的实用框架可以加快开发速度并减少错误数量。

Lodash produces very clean code and promotes a more functional programming style. Lodash 生成非常干净的代码并促进了更函数式的编程风格。 In one glimpse it becomes clear what the intent of the code is.一眼就能看出代码的意图是什么。

OP's issue can simply be solved as: OP的问题可以简单地解决为:

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

More info?更多信息? Eg 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.我们现在可以使用_.property简写user.age来指定应该匹配的属性的路径。 We will sort the user objects by the nested age property.我们将按嵌套的年龄属性对用户对象进行排序。 Yes, it allows for nested property matching!是的,它允许嵌套属性匹配!

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 chain ?想用结合两者吗?

const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();

Or when do you prefer flow over chain或者你什么时候更喜欢流动而不是链条

const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users); 

You can use Easiest Way: Lodash您可以使用最简单的方法: Lodash

( https://lodash.com/docs/4.17.10#orderBy ) https://lodash.com/docs/4.17.10#orderBy

This method is like _.sortBy except that it allows specifying the sort orders of the iteratees to sort by.此方法类似于_.sortBy ,不同之处在于它允许指定要排序的迭代对象的排序顺序。 If orders is unspecified, all values are sorted in ascending order.如果未指定 orders,则所有值都按升序排序。 Otherwise, specify an order of "desc" for descending or "asc" for ascending sort order of corresponding values.否则,为相应值的降序指定“desc”或“asc”为升序排序。

Arguments论据

collection (Array|Object): The collection to iterate over.集合(数组|对象):要迭代的集合。 [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): The iteratees to sort by. [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): 要排序的迭代对象。 [orders] (string[]): The sort orders of iteratees. [orders] (string[]):迭代的排序顺序。

Returns退货

(Array): Returns the new sorted array. (Array):返回新的排序数组。


var _ = require('lodash');
var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];
    
_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);

I haven't seen this particular approach suggested, so here's a terse comparison method I like to use that works for both string and number types:我还没有看到建议的这种特殊方法,所以这是我喜欢使用的一种简洁的比较方法,它适用于stringnumber类型:

 const objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; const sortBy = fn => { const 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));

Explanation of sortBy() sortBy()的解释

sortBy() accepts a fn that selects a value from an object to use in comparison, and returns a function that can be passed to Array.prototype.sort() . sortBy()接受一个从对象中选择一个值进行比较的fn ,并返回一个可以传递给Array.prototype.sort()的函数。 In this example, we're comparing o.last_nom .在此示例中,我们正在比较o.last_nom Whenever we receive two objects such as每当我们收到两个对象时,例如

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

we compare them with (a, b) => cmp(fn(a), fn(b)) .我们将它们与(a, b) => cmp(fn(a), fn(b))进行比较。 Given that鉴于

fn = o => o.last_nom

we can expand the comparison function to (a, b) => cmp(a.last_nom, b.last_nom) .我们可以将比较函数扩展为(a, b) => cmp(a.last_nom, b.last_nom) Because of the way logical OR ( || ) works in JavaScript, cmp(a.last_nom, b.last_nom) is equivalent to由于逻辑或 ( || )在 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;

Incidentally, this is called the three-way comparison "spaceship" ( <=> ) operator in other languages.顺便说一句,这在其他语言中称为三向比较“宇宙飞船”( <=> )运算符

Finally, here's the ES5-compatible syntax without using arrow functions:最后,这是不使用箭头函数的 ES5 兼容语法:

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; function sortBy(fn) { function cmp(a, b) { return -(a < b) || +(a > b); } return function (a, b) { return cmp(fn(a), fn(b)); }; } function getLastName(o) { return o.last_nom; } var sortByLastName = sortBy(getLastName); objs.sort(sortByLastName); console.log(objs.map(getLastName));

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

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].其中fn1 , fn2 , ... 是返回 [-1,0,1] 的排序函数。 This results in "sorting by fn1", "sorting by fn2" which is pretty much equal to ORDER BY in SQL.这导致“按 fn1 排序”、“按 fn2 排序”,这几乎等于 SQL 中的 ORDER 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.这里的重点是,使用函数式方法的纯 JavaScript 可以带您走很长一段路,而无需外部库或复杂代码。 It is also very effective, since no string parsing have to be done它也非常有效,因为不必进行字符串解析

Try this,尝试这个,

UPTO ES5

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


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


IN ES6 & above:

// Ascending sort
items.sort((a, b) => a.value - b.value);

// Descending Sort
 items.sort((a, b) => b.value - a.value);

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}
 */
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;
  };
};

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: 'Mashraki',          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'));

为什么不写短代码?

objs.sort((a, b) => a.last_nom > b.last_nom ? 1 : -1)

Sorting (more) Complex Arrays of Objects排序(更多)复杂的对象数组

Since you probably encounter more complex data structures like this array, I would expand the solution.由于您可能会遇到像这个数组这样更复杂的数据结构,我将扩展解决方案。

TL;DR TL;博士

Are more pluggable version based on @ege-Özcan 's very lovely answer .是基于@ege-Özcan非常可爱的答案的更多可插拔版本。

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目标是主要按People.Name.name排序,其次按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.另一方面,简单地做People['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://stackoverflow.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 上的工作示例

Use JavaScript sort method使用 JavaScript sort方法

The sort method can be modified to sort anything like an array of numbers, strings and even objects using a compare function.可以修改sort方法以使用比较函数对数字、字符串甚至对象数组等任何内容进行排序。

A compare function is passed as an optional argument to the sort method.比较函数作为可选参数传递给 sort 方法。

This compare function accepts 2 arguments generally called a and b .此比较函数接受 2 个参数,通常称为ab Based on these 2 arguments you can modify the sort method to work as you want.基于这 2 个参数,您可以修改排序方法以根据需要工作。

  1. If the compare function returns less than 0, then the sort() method sorts a at a lower index than b .如果 compare 函数返回小于 0,则sort()方法在比b低的索引处对a进行排序。 Simply a will come before b.简单地说,a 将出现在 b 之前。
  2. If the compare function returns equal to 0, then the sort() method leaves the element positions as they are.如果比较函数返回等于 0,则sort()方法将元素位置保持原样。
  3. If the compare function returns greater than 0, then the sort() method sorts a at greater index than b .如果比较函数返回大于 0,则sort()方法在比b更大的索引处对a进行排序。 Simply a will come after b .只是a会在b之后。

Use the above concept to apply on your object where a will be your object property.使用上述概念应用于您的对象,其中a将是您的对象属性。

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; 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); console.log(objs) // for better look use console.table(objs)
输出

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.默认按升序排序。

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()'是必要的,以防止在比较字符串时出错。

Warning!警告!
Using this solution is not recommended as it does not result in a sorted array.不建议使用此解决方案,因为它不会导致排序数组。 It is being left here for future reference, because the idea is not rare.它留在这里供将来参考,因为这个想法并不罕见。

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

This is my take on this:<\/i>这是我对此的看法:<\/b><\/p>

The order<\/code> parameter is optional and defaults to "ASC" for ascending order.<\/i> order<\/code>参数是可选的,默认为“ASC”表示升序。<\/b><\/p>

Works on accented chars and it's case insensitive<\/strong> .<\/i>适用于重音字符并且不区分大小写<\/strong>。<\/b><\/p>

NOTE:<\/strong> It sorts and returns the ORIGINAL<\/strong> array.<\/i>注意:<\/strong>它排序并返回原始<\/strong>数组。<\/b><\/p>

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

additional desc params for Ege Özcan code Ege Özcan代码的附加 desc 参数

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

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

Given the original example:给定原始示例:

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

Sort by multiple fields:按多个字段排序:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

Notes笔记

  • a.localeCompare(b) is universally supported and returns -1,0,1 if a<b , a==b , a>b respectively. a.localeCompare(b)得到普遍支持,如果a<ba==ba>b分别返回 -1,0,1 。
  • || in the last line gives last_nom priority over first_nom .在最后一行中, last_nom优先于first_nom
  • Subtraction works on numeric fields: var age_order = left.age - right.age;减法适用于数字字段: var age_order = left.age - right.age;
  • Negate to reverse order, return -last_nom_order || -first_nom_order || -age_order;取反顺序, return -last_nom_order || -first_nom_order || -age_order; return -last_nom_order || -first_nom_order || -age_order;

A simple function that sort an array of object by a property一个按属性对对象数组进行排序的简单函数

function sortArray(array, property, direction) {
    direction = direction || 1;
    array.sort(function compare(a, b) {
        let comparison = 0;
        if (a[property] > b[property]) {
            comparison = 1 * direction;
        } else if (a[property] < b[property]) {
            comparison = -1 * direction;
        }
        return comparison;
    });
    return array; // Chainable
}

Usage:用法:

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

sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc
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"));

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)

You can use a reusable sort function.您可以使用可重用的排序功能。

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

Its can be use to sort both Array and Object in array它可用于对数组中的数组对象进行排序
. .

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 (optional) > to sort object contain in array.第一个(可选) > 对包含在数组中的对象进行排序。
2rd is method > { reverse: any, insensitive: any }第二个是方法> { reverse: any, insensitive: any }

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试试这个例子。

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

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

})

Way 1 :方式1:

You can use Underscore.js .您可以使用Underscore.js Import underscore first.先导入下划线。

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

Way 2 : Use compare function.方式2:使用比较功能。

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

objs.sort(compare);

Simple answer:简单的回答:

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

Details:细节:

Today it is very simple, You can compare strings with localeCompare .今天很简单,你可以用localeCompare比较字符串。 As the Mozilla Doc says:正如 Mozilla Doc 所说:

The localeCompare() method returns a number indicating whether a reference string comes before , or after , or is the same as the given string in sort order . localeCompare()方法返回一个数字,指示引用字符串是在排序顺序beforeafter还是is the same as the given string in sort order

    //example1:
    console.log("aaa".localeCompare("aab")); //-1
    console.log("aaa".localeCompare("aaa")); //0
    console.log("aab".localeCompare("aaa")); //1

    //example2:
    const a = 'réservé'; // with accents, lowercase
    const b = 'RESERVE'; // no accents, uppercase

    console.log(a.localeCompare(b));
    // expected output: 1
    console.log(a.localeCompare(b, 'en', { sensitivity: 'base' }));
    // expected output: 0

For more details see Mozilla doc localeCompare :有关更多详细信息,请参阅 Mozilla 文档localeCompare

It works for me.这个对我有用。 Here It will keep undefined to the end.在这里它将保持未定义到最后。

 function sort(items, property, direction) { function compare(a, b) { if(!a[property] && !b[property]) { return 0; } else if(a[property] && !b[property]) { return -1; } else if(!a[property] && b[property]) { return 1; } else { const value1 = a[property].toString().toUpperCase(); // ignore upper and lowercase const value2 = b[property].toString().toUpperCase(); // ignore upper and lowercase if (value1 < value2) { return direction === 0 ? -1 : 1; } else if (value1 > value2) { return direction === 0 ? 1 : -1; } else { return 0; } } } return items.sort(compare); } var items = [ { name: 'Edward', value: 21 }, { name: 'Sharpe', value: 37 }, { name: 'And', value: 45 }, { name: 'The', value: -12 }, { name: undefined, value: -12 }, { name: 'Magnetic', value: 13 }, { name: 'Zeros', value: 37 } ]; console.log('Ascending Order:- '); console.log(sort(items, 'name', 0)); console.log('Decending Order:- '); console.log(sort(items, 'name', 1));

Sorting objects with Intl.Collator for the specific case when you want natural sorting (ie 1,2,10,11,111 ).当您想要自然排序(即1,2,10,11,111 )时,使用Intl.Collator对特定情况下的对象进行排序。

 const files = [ {name: "1.mp3", size: 123}, {name: "10.mp3", size: 456}, {name: "100.mp3", size: 789}, {name: "11.mp3", size: 123}, {name: "111.mp3", size: 456}, {name: "2.mp3", size: 789}, ]; const naturalCollator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); files.sort((a, b) => naturalCollator.compare(a.name, b.name)); console.log(files);

Browser support for Intl.Collator浏览器对Intl.Collator的支持

Using xPrototype : https://github.com/reduardo7/xPrototype/blob/master/README.md#sortbycol1-col2-coln使用xPrototypehttps ://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"}
*/

I Just enhanced Ege Özcan 's dynamic sort to dive deep inside objects.我刚刚增强了Ege Özcan的动态排序以深入对象内部。 If Data looks like this:如果数据看起来像这样:

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 aa property I think my enhancement helps very well.如果您想通过aa属性对其进行排序,我认为我的增强功能非常有用。 I add new functionality to objects like this:我向这样的对象添加新功能:

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 aa this way:现在您可以通过这种方式按aa排序:

obj.sortBy('a.a');

See Commplete script in JSFiddle请参阅JSFiddle中的完整脚本

使用 lodash 或 Underscore,它是小菜一碟

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc

I've been using this utility in a variety of projects and it works great.我一直在各种项目中使用此实用程序,并且效果很好。 It's very modular too:它也非常模块化:

  • Pass the name of the key to sort by传递要排序的键名
  • Choose if the sorting is ascending or descending选择排序是升序还是降序

sortArrayOfObjsByKeyUtil.js sortArrayOfObjsByKeyUtil.js

// Sort array of objects by key
// ------------------------------------------------------------
const sortArrayOfObjsByKey = (array, key, ascdesc) =>
  array.sort((a, b) => {
    const x = a[key];
    const y = b[key];
    if (ascdesc === 'asc') {
      return x < y ? -1 : x > y ? 1 : 0;
    }
    if (ascdesc === 'desc') {
      return x > y ? -1 : x < y ? 1 : 0;
    }
    return null;
  });

sortArrayOfObjsByKeyUtil.test.js sortArrayOfObjsByKeyUtil.test.js

import sortArrayOfObjsByKey from './sortArrayOfObjsByKeyUtil';

const unsortedArray = [
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
];

const sortedArray = [
  {
    _id: 'cd00459f-3755-49f1-8847-66591ef935b2',
    title: 'Home',
    address: {
      PostalAddress: {
        streetAddress: 'Stockfleths gate 58A',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0461',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.937316, lng: 10.751862 },
  },
  {
    _id: '3df55221-ce5c-4147-8e14-32effede6133',
    title: 'Netlife Design',
    address: {
      PostalAddress: {
        streetAddress: 'Youngstorget 3',
        addressLocality: 'Oslo',
        addressRegion: null,
        postalCode: '0181',
        addressCountry: 'Norway',
      },
    },
    geopoint: { lat: 59.914322, lng: 10.749272 },
  },
];

describe('sortArrayOfObjsByKey', () => {
  it(`sort array by 'title' key, ascending`, () => {
    const testInput = sortArrayOfObjsByKey(unsortedArray, 'title', 'asc');
    const testOutput = sortedArray;
    expect(testInput).toEqual(testOutput);
  });
});

It is also possible to make a dynamic sorting function when programming in TypeScript , but the types become more tricky in this case.TypeScript中编程时也可以创建动态排序功能,但在这种情况下类型变得更加棘手。

function sortByKey<O>(key: keyof O, decending: boolean = false): (a: O, b: O) => number {
    const order = decending ? -1 : 1;
    return (a, b): number => {
        const valA = a[key];
        const valB = b[key];
        if (valA < valB) {
            return -order;
        } else if (valA > valB) {
            return order;
        } else {
            return 0;
        }
    }
}

This can be used in TypeScript as the following:这可以在 TypeScript 中使用,如下所示:

const test = [
    {
        id: 0,
    },
    {
        id: 2,
    }
]

test.sort(sortByKey('id')) // OK
test.sort(sortByKey('id1')) // ERROR
test.sort(sortByKey('')) // ERROR

this sorting funciton can be use for all object sorting,此排序功能可用于所有对象排序,

  • object目的

  • deepObject深度对象

  • numeric array数值数组

you can also do assending or desending sort by passing 1,-1 as param您还可以通过将 1,-1 作为参数传递来进行 assending 或 desending 排序

 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; } }); function dynamicSortAll(property,sortOrders=1) { /**default sorting will be ascending order if you need descending order sording you have to pass -1 as param**/ var sortOrder = sortOrders; return function (a,b) { var result =(property? ((a.deepVal(property) > b.deepVal(property)) ? 1 : (a.deepVal(property) < b.deepVal(property)) ? -1 : 0) :((a > b) ? 1 : (a < b) ? -1 : 0)) return result * sortOrder; } } deepObj = [ { 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 } }]; let deepobjResult=deepObj.sort(dynamicSortAll('a.a',1)) console.log('deepobjResult :'+ JSON.stringify(deepobjResult)) var obj = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' } ]; let objResult=obj.sort(dynamicSortAll('last_nom',1)) console.log('objResult :'+ JSON.stringify(objResult)) var numericObj=[1,2,3,4,5,6] let numResult=numericObj.sort(dynamicSortAll(null,-1)) console.log('numResult :'+ JSON.stringify(numResult)) let stringSortResult='helloworld'.split('').sort(dynamicSortAll(null,1)) console.log('stringSortResult:'+ JSON.stringify(stringSortResult)) let uniqueStringOrger=[...new Set(stringSortResult)]; console.log('uniqueStringOrger:'+ JSON.stringify(uniqueStringOrger))

Deep深的

Based on this excellent tutorial I would like to develop Vlad Bezden answer and explain why localeCompare is better than standard comarison method like strA > strB .基于这个优秀的教程,我想开发Vlad Bezden 的答案并解释为什么localeComparestrA > strB等标准comarison方法更好。 Lets run this example让我们运行这个例子

 console.log( 'Österreich' > 'Zealand' ); // We expect false console.log( 'a' > 'Z' ); // We expect false

The reason is that in JS all strings are encoded using UTF-16 and原因是在 JS 中所有字符串都使用UTF-16编码,并且

 let str = ''; // order of characters in JS for (let i = 65; i <= 220; i++) { str += String.fromCodePoint(i); // code to character } console.log(str);

Capital letters go first (have small codes) and then go small letters and then go character Ö (after z ).大写字母在前(有小代码),然后是小写字母,然后是字符Ö (在z之后)。 This is reason why we get true in first snippet - becasue operator > compare characters codes.这就是为什么我们在第一个片段中得到正确的原因 - 因为运算符>比较字符代码。

As you can see compare characters in diffrent languages is non trivial task - but luckily, modern browsers support the internationalization standard ECMA-402 .正如您所见,比较不同语言中的字符并非易事——但幸运的是,现代浏览器支持国际化标准ECMA-402 So in JS we have strA.localeCompare(strB) which do the job ( -1 means strA is less than strB ; 1 means opposite; 0 means equal)所以在 JS 中我们有strA.localeCompare(strB)来完成这项工作( -1表示strA小于strB ;1 表示相反;0 表示相等)

 console.log( 'Österreich'.localeCompare('Zealand') ); // We expect -1 console.log( 'a'.localeCompare('Z') ); // We expect -1

I would like to add that localeCompare supports two parameters: language and additional rules我想补充一点, localeCompare支持两个参数:语言和附加规则

 var objs = [ { first_nom: 'Lazslo', last_nom: 'Jamf' }, { first_nom: 'Pig', last_nom: 'Bodine' }, { first_nom: 'Pirate', last_nom: 'Prentice' }, { first_nom: 'Test', last_nom: 'jamf' } ]; objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom,'en',{sensitivity:'case'})) console.log(objs); // in '>' comparison 'Jamf' will NOT be next to 'jamf'

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'], reverse=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>

// Sort Array of Objects

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

// Property to Sort By
var args = "last_nom";

// Function to Sort the Data by given Property
function sortByProperty(property) {
    return function (a, b) {
        var sortStatus = 0,
            aProp = a[property].toLowerCase(),
            bProp = b[property].toLowerCase();
        if (aProp < bProp) {
            sortStatus = -1;
        } else if (aProp > bProp) {
            sortStatus = 1;
        }
        return sortStatus;
    };
}

// Implementation
var sortedArray = booksArray.sort(sortByProperty(args));

console.log("sortedArray: " + JSON.stringify(sortedArray) );

Console log output:控制台日志输出:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"

Adapted based on this source: https://web.archive.org/web/20210515081841/http://opnsrce.github.io/code-snippet-how-to-sort-an-array-of-json-objects-by-property基于此来源改编: https ://web.archive.org/web/20210515081841/http://opnsrce.github.io/code-snippet-how-to-sort-an-array-of-json-objects- 副业

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

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 ( ie 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 ,第一个参数items是对象数组,

  • 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. reverse是一个布尔参数,如果为真,则按升序排列,如果为假,则返回降序。

Hers a function you can use to sort the list by multiple objects, where if the first object is equal, the second order will be used as a fallback.她的函数可以用来按多个对象对列表进行排序,如果第一个对象相等,则第二个顺序将用作后备。 empty values should also be ignored to fallback order if possible.如果可能,空值也应忽略回退顺序。

function sortObjects(list, orderBy){
    list.sort(function(a, b){
        let byIndex = 0;
        let order = orderBy[byIndex];
        while(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            byIndex++;
            if(byIndex >= orderBy.length){break;}
            order = orderBy[byIndex];
        }
        if(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            return false;
        }
        if(order.desc){
            return a[order.by] < b[order.by];
        }
        return a[order.by] > b[order.by];
    });
    return list;
}

usage:用法:

var objs = [
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
];

sortObjectList(objs, [{by: 'a'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 20, b: 10, c: 30},
    {a: 30, b: 10, c: 20},
]

sortObjectList(objs, [{by: 'a', desc: true}]);
[
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
    {a: 10, b: 20, c: 30},
]

sortObjectList(objs, [{by: 'b', desc: true}, {by: 'c'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
]

another example:另一个例子:

var objs = [
    {a: 5, b: 5},
    {a: 10, b: 15},
    {a: 15, b: 25},
    {b: 10},
    {b: 20},
    {a: 10, b: 30},
    {a: 10, b: 12},
];

sortObjectList(objs, [{by: 'a'}, {by: 'b'}]);
[
    {a: 5, b: 5},
    {b: 10},
    {a: 10, b: 12},
    {a: 10, b: 15},
    {b: 20},
    {a: 10, b: 30},
    {a: 15, b: 25},
]

For fp-holics:对于 fp-holics:

const objectSorter = (p)=>(a,b)=>((a,b)=>a>b?1:a<b?-1:0)(a[p], b[p]);
objs.sort(objectSorter('first_nom'));

I will give you a solution implementing selectionSort algorithm ,it is simple and effective我会给你一个实现选择排序算法的解决方案,它简单有效

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


function selection_Sort(num) { 
 //console.log(num);  
 var temp, index;
 for (var i = 0; i <= num.length - 1; i++) {
index = i;
for (var j = i + 1; j <= num.length - 1; j++) {
 // you can use first_nom/last_nom,any way you choose to sort

  if (num[j]. last_nom < num[index]. last_nom) {
    index = j;
  } 
}

//below is the swapping part
temp = num[i]. last_nom;
num[i]. last_nom = num[index]. last_nom;
num[index]. last_nom = temp;
 };
 console.log(num); 
 return num; 
  }
  selection_Sort(objs);

Great to see such great answers很高兴看到这么好的答案

In case you have nested objects如果您有嵌套对象

const objs = [{
        first_nom: 'Lazslo',
        last_nom: 'Jamf',
        moreDetails: {
            age: 20
        }
    }, {
        first_nom: 'Pig',
        last_nom: 'Bodine',
        moreDetails: {
            age: 21
        }
    }, {
        first_nom: 'Pirate',
        last_nom: 'Prentice',
        moreDetails: {
            age: 22
        }
    }];

nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
        const a = prop2 ? e1[prop1][prop2] : e1[prop1],
            b = prop2 ? e2[prop1][prop2] : e2[prop1],
            sortOrder = direction === "asc" ? 1 : -1
        return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
    }

and call it like并称它为

objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));
//Try this way


let objs = [ 
        { first_nom: 'Lazslo', last_nom: 'Jamf'     },
        { first_nom: 'Pig',    last_nom: 'Bodine'   },
        { first_nom: 'Pirate', last_nom: 'Prentice' }
    ];
    const compareBylastNom = (a, b) => {
        // converting to uppercase to have case-insensitive comparison
        const name1 = a.last_nom.toUpperCase();
        const name2 = b.last_nom.toUpperCase();
    
        let comparison = 0;
    
        if (name1 > name2) {
            comparison = 1;
        } else if (name1 < name2) {
            comparison = -1;
        }
        return comparison;
    }
    console.log(objs.sort(compareBylastNom));

I know there is already plenty of answers, including those with localeCompare ones, but if you don't want to/can't use localeCompare for some reason, I would suggest you to use this solution instead of ternary operator solution:我知道已经有很多答案,包括那些带有 localeCompare 的答案,但是如果您出于某种原因不想/不能使用 localeCompare,我建议您使用此解决方案而不是三元运算符解决方案:

objects.sort((a, b) => (a.name > b.name) - (a.name < b.name));

Someone could say that it's not obvious what this code is doing, but in my opinion ternary operator is worse.有人可能会说这段代码在做什么并不明显,但在我看来,三元运算符更糟。 If one ternary operator is readable enough, two ternary operators one embedded into another — really hard to read and ugly.如果一个三元运算符足够可读,则两个三元运算符一个嵌入另一个 - 真的很难阅读和丑陋。 One-line code with just two comparison operators and one minus operator is very simple to read and thus to reason.只有两个比较运算符和一个减号运算符的一行代码非常易于阅读和推理。

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'

I would do it like this:我会这样做:

[...objs].sort((a, b) => a.last_nom.localeCompare(b.last_nom))
  var objs = [ 
    { firstName: 'A', lastName: 'Mark'  }, // b
    { firstName: 'E', lastName: 'askavy' }, // a
    { firstName: 'C', lastName: 'peter' }
];

objs.sort((a,b) => {
   return a.firstName.localeCompare(b.firstName) // Sort Ascending 
}) 

objs.sort((a,b) => {
   return b.firstName.localeCompare(a.firstName) // Sort Decending
}) 

 console.log(objs)

i use this solution:我使用这个解决方案:

use yourArrayName.sort(); // ascending
use yourArrayName.sort().reverse(); // descending

I do like below.我喜欢下面。

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

objs.sort(function(a, b) {
  const nameA = a.name.toUpperCase(); // ignore upper and lowercase
  const nameB = b.name.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }
  // names must be equal
  return 0;
});

console.log(arr);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM