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

问:

我有一组 JavaScript 对象:

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

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

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

答1:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

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

或内联(c/o Marco Demaio):

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

或简化为数字(c/o Andre Figueiredo):

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

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

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

官方文档:developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…

return a.last_nom.localeCompare(b.last_nom) 也可以。

对于那些寻找字段为数字的排序的人,比较函数体:return a.value - b.value;(ASC)

您可以使用 charCodeAt 将字符串转换为数字,然后使用上面的数字内联以获得更简洁的一行:objs.sort((a,b) => a.last_nom.charCodeAt(0) - b.last_nom.charCodeAt(0));。这避免了丑陋的嵌套三元组。

答2:

huntsbot.com – 高效赚钱,自由工作

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

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

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

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

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

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

其实这已经回答了这个问题。以下部分是因为很多人联系我,抱怨it doesn’t work with multiple 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;
    }
}

这将使您能够执行以下操作:

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

子类化数组

对于我们当中可以使用 ES6 的幸运儿,它允许扩展原生对象:

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

这将实现这一点:

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

好的。现在有这个答案的 Typescript 版本:stackoverflow.com/a/68279093/8910547。保持(类型)安全! 😉

你永远不应该扩展 Array.

@zero_cool 数组没有在这里扩展(原型保持不变),它是从扩展而来的。您确实不应该更改本机对象的原型,但正如我所说,这不是这里发生的事情。

答3:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

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

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

在 ES6/ES2015 之前

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

这自 JS 1.1 起就可用,与此相关的胖箭头部分是 ES6/2015 部分。但仍然非常有用,我认为最好的答案

@PratikKelwalkar:如果您需要反转它只需切换 a 和 b 比较: objs.sort((a, b) => b.last_nom.localeCompare(a.last_nom));

如果值是数字,则不需要 localeCompare。您可以使用标准的 > 运算符 - 就像@muasif80 的答案中提到的那样 - stackoverflow.com/a/67992215/6908282

目前这个问题的更简单的解决方案。

恕我直言,这应该是公认的答案

答4:

huntsbot.com – 高效赚钱,自由工作

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

大卫,您能否将答案编辑为 var sortedObjs = _.sortBy( objs, 'first_nom' );。 objs 将不会因此而自行排序。该函数将返回一个排序数组。这将使它更加明确。

反向排序:var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();

您需要加载 javascript 库“下划线”:

也可以在 Lodash 中为喜欢那个的人提供

在 lodash 中这将是相同的:var sortedObjs = _.sortBy( objs, 'first_nom' ); 或者如果您希望它以不同的顺序:var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );

答5:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

区分大小写

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

不区分大小写

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

有用的说明

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

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

var objs = [ { first_nom: ‘Lazslo’, last_nom: ‘Jamf’ }, { first_nom: ‘Pig’, last_nom: ‘Bodine’ }, { first_nom: ‘海盗’, last_nom: ‘Prentice’ } ]; // 定义几个排序回调函数,一个带有硬编码排序键,另一个带有参数排序键 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(“使用 sorter1 - 硬编码排序属性 last_name”, objs); objs.sort(sorter2(‘first_nom’)); console.log(“使用 sorter2 - 传递参数 sortBy=‘first_nom’”, objs); objs.sort(sorter2(‘last_nom’)); console.log(“使用 sorter2 - 传递参数 sortBy=‘last_nom’”, objs);

区分大小写的方法是一种很好的速记方式——尤其是当值是数字或日期时。

提示:如果您想颠倒顺序,您可以简单地将 -1 和 1 交换为例如:从 1 : -1 到 -1 : 1

改变 (a, b) to (b, a) 怎么样 :)

是的,这也有效。我只是发现交换 1 & -1 更直接和合乎逻辑。

@Gangula:与参数名称相反的顺序也更容易获取,但我想无论如何都会有更多的代码阅读经验(在维护的情况下)。我最喜欢的是省略另一个测试以使项目保持不变(返回 0)以防它们相同......如果项目相同,我不介意交换。

答6:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

如果您有重复的姓氏,则可以按名字对它们进行排序-

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

@BadFeelingAboutThis 返回 -1 或 1 是什么意思?我知道 -1 字面意思是仅通过语法 A 小于 B,但是为什么要使用 1 或 -1 呢?我看到每个人都在使用这些数字作为返回值,但为什么呢?谢谢。

@Chris22 返回的负数意味着 b 应该在数组中的 a 之后。如果返回正数,则表示 a 应该在 b 之后。如果返回 0,则表示它们被视为相等。您可以随时阅读文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

@BadFeelingAboutThis 感谢您的解释和链接。信不信由你,在我在这里问这个问题之前,我使用 1, 0, -1 搜索了各种代码片段。我只是没有找到我需要的信息。

答7:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

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

在问题中,字符串用于比较而不是数字。您的答案非常适合按数字排序,但不适用于按字符串进行比较。

用于比较对象属性(本例中为 numbers)的 a.value - b.value 可用于不同时间的数据。例如,正则表达式可用于比较每对相邻的字符串。

如果您需要按 ID 对其进行排序,则此实现非常好。是的,您建议使用正则表达式来比较相邻的字符串,这会使解决方案更加复杂,而如果将正则表达式与给定的解决方案一起使用,则此简化版本的目的将是其他情况。简单是最好的。

答8:

huntsbot.com – 高效赚钱,自由工作

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

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

示例/用法

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

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

它不只是返回另一个数组。但实际上对原始的进行排序!

如果您想确保使用数字的自然排序(即 0、1、2、10、11 等...),请使用带有 Radix 集的 parseInt。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 所以:返回 (parseInt(a[p],10) > parseInt(b[p],10)) ? 1 : (parseInt(a[p],10) < parseInt(b[p],10)) ? -1:0;

@codehuntr 感谢您的纠正。但我想与其制作排序函数来进行这种敏感化,不如制作一个单独的函数来修复数据类型。因为排序函数不能不知道哪个属性会包含什么样的数据。 :)

我认为这仅适用于某些道具类型..您想添加日期/字符串处理等..即如果类型是字符串,则使用 return a.localCompare(b) 等..等等。

答9:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

不正确的旧答案:

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

更新

来自 Beauchamp 的评论:

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

更易读的格式:

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

没有嵌套三元组:

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

说明:Number() 会将 true 转换为 1 并将 false 转换为 0。

它有效,但由于某种原因结果不稳定

@AO17 不,不会。你不能减去字符串。

应该这样做:arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

@Jean-FrançoisBeauchamp,您的解决方案效果很好,而且效果更好。

为什么 arr.sort((a, b) => a.name > b.name ? 1 : -1 不起作用?对于我已经测试过的字符串,这很好用。如果您希望不区分大小写,请使用 a.name.toLowerCase() 和 b.name.toLowerCase()

答10:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

Lodash.js(Underscore.js 的超集)

最好不要为每个简单的逻辑添加框架,但是依靠经过良好测试的实用框架可以加快开发速度并减少错误数量。

Lodash 生成非常干净的代码并促进了更函数式的编程风格。一眼就能看出代码的意图是什么。

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

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

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

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

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

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

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

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

想要使用 chain 将两者结合起来吗?

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

或者你什么时候更喜欢 flow 而不是链

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

答11:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

您可以使用最简单的方法:Lodash

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

此方法与 _.sortBy 类似,只是它允许指定要排序的迭代对象的排序顺序。如果未指定 orders,则所有值都按升序排序。否则,为相应值的降序指定“desc”或“asc”为升序排序。

论据

集合(数组|对象):要迭代的集合。 [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']);

原文链接:https://www.huntsbot.com/qa/9rXV/sort-array-of-objects-by-string-property-value?lang=zh_CN&from=csdn

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值