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

Tyr*_*rop 2535 javascript arrays sorting

我有一个JavaScript对象数组:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
Run Code Online (Sandbox Code Playgroud)

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

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

Wog*_*gan 3651

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

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 );
Run Code Online (Sandbox Code Playgroud)

或内联(c/o Marco Demaio):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 
Run Code Online (Sandbox Code Playgroud)

  • 或者内联:objs.sort(function(a,b){return(a.last_nom> b.last_nom)?1:((b.last_nom> a.last_nom)? - 1:0);}); (404认同)
  • `return a.last_nom.localeCompare(b.last_nom)`也可以. (156认同)
  • 对于那些寻找字段为数字的排序的人来说,比较函数体:`return a.value - b.value;`(ASC) (138认同)
  • 官方文档:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort (35认同)
  • @Cerbrus`localeCompare`在外语中使用重音字符时很重要,也更优雅. (15认同)
  • 我知道创建一个完整的比较函数是冗长的,但是人类会让逻辑更容易.谢谢. (2认同)
  • 您可以使用“charCodeAt”将字符串转换为数字,然后使用上面的数字内联来获得更简洁的内联:“objs.sort((a,b) =&gt; a.last_nom.charCodeAt(0) - b”。 last_nom.charCodeAt(0));`。这避免了丑陋的嵌套三元。 (2认同)

Ege*_*can 805

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];
Run Code Online (Sandbox Code Playgroud)

......当你这样做时它会起作用:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
Run Code Online (Sandbox Code Playgroud)

实际上这已经回答了这个问题.下面的部分是因为许多人联系我,抱怨它不适用于多个参数.

多个参数

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将使您能够做到这样的事情:

People.sort(dynamicSortMultiple("Name", "-Surname"));
Run Code Online (Sandbox Code Playgroud)

将它添加到原型

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

我不建议更改本机对象原型,只是为了给出一个示例,以便您可以在自己的对象上实现它(对于支持它的环境,您也可以使用Object.defineProperty,如下一节所示,至少没有可枚举的负面副作用,如最后一部分所述)

原型实现将类似于以下(这是一个工作示例):

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple.apply(null, args));
    }
}
Run Code Online (Sandbox Code Playgroud)

将其添加到原型的"OK"方式

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

MyArray.from(People).sortBy("Name", "-Surname");
Run Code Online (Sandbox Code Playgroud)

绑定运算符到达之前,这可以是可接受的折衷方案.

所有这些原型乐趣都可以实现:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你应该读这个

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

邪恶

看到最后一个"SortBy"?是啊.不酷.尽可能使用Object.defineProperty,否则单独保留Array.prototype.

  • 好的。现在这个答案有一个 Typescript 版本:/sf/answers/4779536541/。保持(类型)安全! (10认同)
  • @LloydBanks如果你严格使用这个字符串,那么你可以使用`var result = a [property] .localeCompare(b [property]);`而不是`var result =(a [property] <b [property]) ?-1:([属性]> b [属性])?1:0;`. (5认同)
  • @zero_cool 数组没有在这里扩展(原型保持不变),它是从. 您确实不应该更改本机对象的原型,但正如我所说,这不是这里发生的情况。 (4认同)

Vla*_*den 336

在ES6/ES2015或更高版本中,您可以这样做:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
Run Code Online (Sandbox Code Playgroud)

  • 这是自JS 1.1以来一直可用的,这个胖箭头是ES6/2015的一块.但在我看来仍然非常有用,也是最好的答案 (26认同)
  • @PratikKelwalkar:如果你需要反向它只需切换a和b比较:objs.sort((a,b)=> b.last_nom.localeCompare(a.last_nom)); (12认同)
  • @VladBezden感谢您的回答!这个解决方案是第一个具有非常小的编程工作和正确的排序结果和一个字符串数组,如:["Name1","Name10","Name2","其他东西","Name11"].我使用`objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom,undefined,{numberic:true}))进行排序正常工作; (4认同)

Dav*_*row 185

underscore.js

使用下划线,它小而且很棒......

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' );
Run Code Online (Sandbox Code Playgroud)

  • 大卫,你能编辑答案说,`var sortedObjs = _.sortBy(objs,'first_nom');`.由于这个原因,'objs`将不会被自己排序.该函数将**返回**一个已排序的数组.这会使它更明确. (18认同)
  • 反向排序:`var reverseSortedObjs = _.sortBy(objs,'first_nom').reverse();` (10认同)
  • 也可以在[`Lodash`](https://lodash.com/docs/4.17.5#sortBy)中找到喜欢那个的人 (5认同)
  • 在 lodash 中,这将是相同的:`var sortedObjs = _.sortBy( objs, 'first_nom');` 或者如果你想要不同的顺序: `var sortedObjs = _.orderBy( objs, ['first_nom'], ['dsc'] );` (4认同)
  • 您需要加载javascript库“ underscore”:`&lt;script src =“ http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js”&gt; &lt;/ script&gt; ` (2认同)

p3l*_*lim 175

不要理解为什么人们会这么复杂:

objs.sort(function(a, b){
  return a.last_nom > b.last_nom;
});
Run Code Online (Sandbox Code Playgroud)

对于更严格的引擎:

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

交换运算符以按反向字母顺序排序.

  • 我建议编辑以取出第一个版本.它更简洁,所以看起来更有吸引力,但它不起作用,至少不可靠.如果有人在一个浏览器中尝试它并且它可以工作,他们可能甚至没有意识到他们有问题(特别是如果他们没有阅读评论).第二个版本正常工作,所以第一个版本确实没有必要. (19认同)
  • 这实际上是不正确的,因为sort中使用的函数应该返回-1,0或1,但上面的函数返回一个布尔值.排序在chrome中运行良好,但在PhantomJS中失败.请参阅https://code.google.com/p/phantomjs/issues/detail?id=1090 (16认同)
  • @Simon我真的很感激首先使用"略有错误"的版本,因为更严格的实现需要几秒钟来解析和理解,没有它会更难. (2认同)

ken*_*bec 61

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

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;
});
Run Code Online (Sandbox Code Playgroud)

  • 那个`a <b``a> b`格式很有趣. (43认同)

Vin*_*wal 45

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

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;
  });
}
Run Code Online (Sandbox Code Playgroud)

示例/用法

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"}]
Run Code Online (Sandbox Code Playgroud)

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

  • 它不仅仅是返回另一个数组.但实际上对原来的那个进行了分类! (5认同)
  • 从来没有建议过修改核心对象原型的解决方案 (3认同)

0le*_*leg 34

截至2018年,有一个更短,更优雅的解决方案.只是用.Array.prototype.sort().

例:

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;
});
Run Code Online (Sandbox Code Playgroud)

  • 在问题中,字符串用于比较而不是数字.您的答案非常适合按数字排序,但不太适合按字符串进行比较. (6认同)

Sat*_*pta 30

使用JavaScriptsort方法

可以修改该sort方法以使用比较函数对数字数组、字符串甚至对象等任何内容进行排序。

比较函数作为可选参数传递给排序方法。

该比较函数接受 2 个参数,通常称为ab。基于这两个参数,您可以修改排序方法以按您想要的方式工作。

  1. 如果比较函数返回小于 0,则该sort()方法将a排序为比b更低的索引。简单地说,a 将出现在 b 之前。
  2. 如果比较函数返回等于 0,则该sort()方法将元素位置保持原样。
  3. 如果比较函数返回大于 0,则该sort()方法按比b更大的索引对a进行排序。只是a会出现在b之后。

使用上述概念应用于您的对象,其中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)
Run Code Online (Sandbox Code Playgroud)
输出


Chr*_*oph 29

您也可以使用自定义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();
Run Code Online (Sandbox Code Playgroud)


Har*_*hal 26

您可以使用

最简单的方法:Lodash

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

此方法类似于_.sortBy,但它允许指定迭代的排序顺序以进行排序.如果未指定订单,则所有值都按升序排序.否则,为降序指定"desc"的顺序,或为相应值的升序排序指定"asc".

参数

collection(Array | Object):要迭代的集合.[iteratees = [_.identity]](Array [] | Function [] | Object [] | string []):迭代次数排序依据.[orders](string []):迭代的排序顺序.

返回

(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']);
Run Code Online (Sandbox Code Playgroud)


小智 26

尝试这个,

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);
Run Code Online (Sandbox Code Playgroud)

  • 对我来说不起作用,尝试了其他确实有效的解决方案,但这个不起作用。尝试按字符串排序。 (3认同)
  • 最佳且简单的解决方案 (2认同)

Nic*_*lle 23

Lodash.js(超集Underscore.js)

最好不要为每一个简单的逻辑片段添加一个框架,但依靠经过良好测试的实用程序框架,加快开发速度并减少写入的错误数量并不是一件容易的事.

Lodash生成非常干净的代码并提升了更多功能的编程风格,从而减少了错误.在一瞥中,很明显代码的意图是什么.

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

const sortedObjs = _.sortBy(objs, 'last_nom');
Run Code Online (Sandbox Code Playgroud)

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

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];
Run Code Online (Sandbox Code Playgroud)

我们现在可以使用_.property简写user.age来指定应匹配的属性的路径.我们将通过嵌套的age属性对用户对象进行排序.是的,它允许嵌套属性匹配!

const sortedObjs = _.sortBy(users, ['user.age']);
Run Code Online (Sandbox Code Playgroud)

想要扭转吗?没问题.使用_.reverse.

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));
Run Code Online (Sandbox Code Playgroud)

想要使用Chaining来结合两者吗?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();
Run Code Online (Sandbox Code Playgroud)


Ter*_*nen 22

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

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )
Run Code Online (Sandbox Code Playgroud)

其中fn1,, fn2...是返回[-1,0,1]的排序函数.这导致"按fn1排序","按fn2排序",这几乎等于SQL中的ORDER BY.

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

最简单的形式只有一个内联函数,如下所示:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )
Run Code Online (Sandbox Code Playgroud)

有两个步骤 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)  )
Run Code Online (Sandbox Code Playgroud)

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

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])
Run Code Online (Sandbox Code Playgroud)

此函数可以扩展为支持数字字段,大小写敏感,任意数据类型等.

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

// 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") )
Run Code Online (Sandbox Code Playgroud)

这里的要点是具有功能方法的纯JavaScript可以在没有外部库或复杂代码的情况下走很长的路.它也非常有效,因为不必进行字符串解析


Jam*_*son 21

用法示例:

objs.sort(sortBy('last_nom'));
Run Code Online (Sandbox Code Playgroud)

脚本:

/**
 * @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;
  };
};
Run Code Online (Sandbox Code Playgroud)


Pat*_*rts 19

我没有看到这种特殊方法的建议,所以这里是一个简洁的比较方法我喜欢使用它适用于stringnumber:

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

const sortBy = fn => (a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Run Code Online (Sandbox Code Playgroud)

以下是对以下内容的解释sortBy():

sortBy()接受一个fn从对象中选择要用作比较的值,并返回一个可以直接传递给的函数Array.prototype.sort().在这个例子中,我们将使用o.last_nom作为比较的值,因此每当我们通过Array.prototype.sort()诸如此类接收两个对象时

{ first_nom: 'Lazslo', last_nom: 'Jamf' }
Run Code Online (Sandbox Code Playgroud)

{ first_nom: 'Pig', last_nom: 'Bodine' }
Run Code Online (Sandbox Code Playgroud)

我们用

(a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}
Run Code Online (Sandbox Code Playgroud)

比较它们.

记住这一点fn = o => o.last_nom,我们可以将比较功能扩展到等效功能

(a, b) => {
  const fa = a.last_nom
  const fb = b.last_nom
  return -(fa < fb) || +(fa > fb)
}
Run Code Online (Sandbox Code Playgroud)

逻辑OR ||运算符具有短路功能,这在此非常有用.由于它的工作原理,上述功能的主体意味着

if (fa < fb) return -1
return +(fa > fb)
Run Code Online (Sandbox Code Playgroud)

所以,如果fa < fb我们返回-1,否则如果fa > fb那时我们返回+1,但如果fa == fb,那么fa < fb并且fa > fb是假的,所以它返回false.

作为一个额外的奖励,这里是没有箭头功能的ECMAScript 5.1中的等价物,遗憾的是它并不那么简洁:

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

var sortBy = function (fn) {
  return function (a, b) {
    var fa = fn(a)
    var fb = fn(b)
    return -(fa < fb) || +(fa > fb)
  }
}

var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))
Run Code Online (Sandbox Code Playgroud)


Dam*_*ica 18

我有一段适合我的代码:

arr.sort((a, b) => a.name > b.name)
Run Code Online (Sandbox Code Playgroud)

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

  • 这应该这样做:`arr.sort((a,b)=> a.name <b.name?-1:(a.name> b.name?1:0))` (10认同)
  • @Jean-FrançoisBeauchamp,您的解决方案工作得非常好,而且效果更好。 (3认同)
  • 为什么 `arr.sort((a, b) =&gt; a.name &gt; b.name ? 1 : -1` 不起作用?对于字符串,我已经测试过这个效果很好。如果你想不区分大小写,那么使用 `a.sort((a, b) =&gt; a.name &gt; b.name ? 1 : -1` 不起作用? name.toLowerCase()` 和 b.name.toLowerCase()` (2认同)

mua*_*f80 17

区分大小写

arr.sort((a, b) => a.name > b.name ? 1 : -1);
Run Code Online (Sandbox Code Playgroud)

不区分大小写

arr.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);
Run Code Online (Sandbox Code Playgroud)

笔记

如果顺序没有变化(在相同字符串的情况下),则条件>将失败并-1返回。但是如果字符串相同则返回 1 或 -1 将导致正确的输出

另一种选择是使用>=运算符而不是>

  • 对于相等的项返回非零违反了compareFn 约定。该问题可能不会在 sort() 的当前实现中显现出来,但不能适应未来和/或可能会影响性能。 (3认同)
  • 是的,这也有效。我只是发现交换“1”和“-1”更直接、更符合逻辑。 (2认同)

ccp*_*zza 16

当您需要自然字符串排序(即)Intl.Collator时,针对特定情况对对象进行排序。["1","2","10","11","111"]

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);
Run Code Online (Sandbox Code Playgroud)

注意: 的undefined构造函数参数Intl.Collator代表区域设置,可以是显式的 ISO 639-1 语言代码,例如en,或者是系统默认区域设置undefined

浏览器支持Intl.Collator


a8m*_*a8m 15

我知道这个问题太旧了,但我没有看到任何类似于我的实现.
此版本基于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);
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它的示例:

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'));
Run Code Online (Sandbox Code Playgroud)


elj*_*efe 14

排序(更多)复杂的对象数组

由于您可能会遇到更复杂的数据结构,例如此数组,我会扩展解决方案.

TL; DR

更可插拔的版本基于@ ege-Özcan的非常可爱的答案.

问题

我遇到了下面的内容,无法改变它.我也不想暂时压扁物体.我也不想使用下划线/ lodash,主要是出于性能原因以及自己实现它的乐趣.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
Run Code Online (Sandbox Code Playgroud)

目标

我们的目标是主要通过对它进行排序People.Name.name,其次通过People.Name.surname

障碍

现在,在基本解决方案中使用括号表示法来计算要动态排序的属性.但是,在这里,我们还必须动态构造括号表示法,因为你会期望一些像People['Name.name']工作一样 - 但事实并非如此.

People['Name']['name']另一方面,简单地说,它是静态的,只允许你下降到第n级.

这里的主要补充是走下对象树并确定最后一个叶子的值,你必须指定,以及任何中间叶子.

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

关于JSBin的工作示例

  • 为什么?这不是原始问题的答案,"目标"可以通过People.sort简单解决((a,b)=> {return a.Name.name.localeCompare(b.Name.name)|| a.Name .surname.localeCompare(b.Name.surname)}) (2认同)

Rav*_*rov 11

还有一个选择:

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));
Run Code Online (Sandbox Code Playgroud)

默认情况下按升序排序.


Cai*_*lau 10

一个简单的方法:

objs.sort(function(a,b) {
  return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
Run Code Online (Sandbox Code Playgroud)

看到'.toLowerCase()'在比较字符串时防止错误是必要的.

  • 您可以使用[箭头功能](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)让代码更优雅:`objs.sort((a ,b)=> b.last_nom.toLowerCase()<a.last_nom.toLowerCase());` (4认同)
  • 箭头功能不是ES5值得的.大量的发动机仍然限于ES5.在我的情况下,我发现上面的答案显着更好,因为我在ES5引擎上(由我的公司强制) (2认同)

cbd*_*per 10

这是我对此的看法:

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

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

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

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;
}
Run Code Online (Sandbox Code Playgroud)

片段

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;
}
Run Code Online (Sandbox Code Playgroud)


小智 9

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 9

将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));
}
Run Code Online (Sandbox Code Playgroud)

用法:

// 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");
Run Code Online (Sandbox Code Playgroud)


Fra*_*ard 9

一个简单的函数,用于按属性对对象数组进行排序

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
}
Run Code Online (Sandbox Code Playgroud)

用法:

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
Run Code Online (Sandbox Code Playgroud)


小智 9

你为什么不写短代码?

objs.sort((a, b) => a.last_nom > b.last_nom && 1 || -1)
Run Code Online (Sandbox Code Playgroud)


age*_*hun 8

根据您的示例,您需要按两个字段(姓氏,名字)排序,而不是一个.您可以使用Alasql库在一行中进行此排序:

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

在jsFiddle上试试这个例子.


小智 8

objs.sort(function(a,b){return b.last_nom>a.last_nom})
Run Code Online (Sandbox Code Playgroud)

  • 实际上它似乎不起作用,不得不使用已接受的答案。它没有正确排序。 (2认同)

Nur*_*Nur 8

您可以使用可重用的排序功能。

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);
};
Run Code Online (Sandbox Code Playgroud)

它可用于对array 中的ArrayObject进行排序

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' } ]
Run Code Online (Sandbox Code Playgroud)

第一个(可选) > 对数组中包含的对象进行排序。
二是方法 > { reverse: any, insensitive: any }


小智 7

您可能需要将它们转换为小写以防止混淆.

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

})
Run Code Online (Sandbox Code Playgroud)


Evg*_*nii 7

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"));
Run Code Online (Sandbox Code Playgroud)

  • 请考虑编辑您的帖子,添加更多关于您的代码的作用以及为什么它可以解决问题的解释。大多数只包含代码(即使它有效)的答案通常不会帮助OP理解他们的问题。 (2认同)

Bob*_*ein 7

鉴于原始示例:

var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
Run Code Online (Sandbox Code Playgroud)

按多个字段排序:

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;
});
Run Code Online (Sandbox Code Playgroud)

笔记

  • a.localeCompare(b)普遍支持,并返回1,0,1如果a<b,a==b,a>b分别.
  • ||在最后一行last_nom优先于first_nom.
  • 减法适用于数字字段: var age_order = left.age - right.age;
  • 否定逆序, return -last_nom_order || -first_nom_order || -age_order;


Gil*_*ain 6

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

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;
        }
Run Code Online (Sandbox Code Playgroud)

使用示例:

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

  • 如何在js中实现快速排序是一个简单的解决方案?简单算法但不是简单的解决方案. (5认同)
  • 好吧,让我尝试不同的话:如何重新发明轮子是一个简单的解决方案? (2认同)

Sri*_* Sg 6

使用Ramda,

npm install 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)
Run Code Online (Sandbox Code Playgroud)


Don*_*one 6

let propName = 'last_nom';

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

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

Run Code Online (Sandbox Code Playgroud)


Edu*_*omo 5

使用 xPrototype 的sortBy

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"}
*/
Run Code Online (Sandbox Code Playgroud)


Mor*_*ani 5

我只是增强了EgeÖzcan的动态排序能力,以深入研究内部物体。如果数据如下所示:

obj = [
    {
        a: { a: 1, b: 2, c: 3 },
        b: { a: 4, b: 5, c: 6 }
    },
    { 
        a: { a: 3, b: 2, c: 1 },
        b: { a: 6, b: 5, c: 4 }
}];
Run Code Online (Sandbox Code Playgroud)

如果您想对某个物业进行排序,我认为我的增强功能会非常有帮助。我向这样的对象添加新功能:

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;
    }
});
Run Code Online (Sandbox Code Playgroud)

并更改了_dynamicSort返回函数:

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

现在你可以通过排序AA是这样的:

obj.sortBy('a.a');
Run Code Online (Sandbox Code Playgroud)

见Commplete脚本的jsfiddle


Luk*_*oen 5

对对象数组进行排序

// 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 the 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) );
Run Code Online (Sandbox Code Playgroud)

控制台日志输出:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"
Run Code Online (Sandbox Code Playgroud)

基于此来源改编:代码片段:如何按属性对 JSON 对象数组进行排序


Har*_*hid 5

方式1:

您可以使用Underscore.js。首先导入下划线。

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');
Run Code Online (Sandbox Code Playgroud)

方法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);
Run Code Online (Sandbox Code Playgroud)


cha*_*pta 5

这个对我有用。这里 它将保持undefined到最后。

 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));
    
    
Run Code Online (Sandbox Code Playgroud)


Sey*_*don 5

简单回答:

objs.sort((a,b)=>a.last_nom.localeCompare(b.last_nom))
Run Code Online (Sandbox Code Playgroud)

细节:

今天很简单,您可以将字符串与localeCompare. 正如 Mozilla Doc 所说:

localeCompare()方法返回一个数字,指示引用字符串是before、 或after、 或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
Run Code Online (Sandbox Code Playgroud)

    //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
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅 Mozilla 文档localeCompare


Wal*_*rée 5

我已经在各种项目中使用了这个实用程序,并且效果很好。它也非常模块化:

  • 传递要排序的键的名称
  • 选择升序还是降序排序

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

Run Code Online (Sandbox Code Playgroud)

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

Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1365128 次

最近记录:

5 年,11 月 前