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

1693

我使用AJAX获取了以下对象并将它们存储在一个数组中:

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": "5",
        "city": "New York",
        "state": "NY",
        "zip": "00010",
        "price": "962500"
    }
];

如何使用JavaScript创建一个按照对象的price属性以升序降序排序的函数?


最快的方法是使用isomorphic sort-array模块,它在浏览器和Node中都可以本地运行,支持任何类型的输入、计算字段和自定义排序顺序。 - Lloyd
相关:按对象属性值对数组进行数字排序 - Sebastian Simon
35个回答

2191

按价格升序排序房屋:

homes.sort(function(a, b) {
    return parseFloat(a.price) - parseFloat(b.price);
});

或者在 ES6 版本之后:

homes.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));

这里可以找到一些文档 (链接)

要按降序排列,您可以使用

homes.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));

238
您可以使用 string1.localeCompare(string2) 进行字符串比较。 - bradvido
85
请记住,localeCompare() 是大小写不敏感的。如果你想要大小写敏感的比较,可以使用(string1 > string2) - (string1 < string2)。布尔值被强制转换为整数0和1以计算差异。 - Don Kirkby
3
谢谢更新,@Pointy。我不记得遇到过这个问题,但也许行为在过去几年中已经发生了变化。无论如何,localeCompare()文档表明,您可以明确地指定是否需要区分大小写、数字排序和其他选项。 - Don Kirkby
5
我认为你误解了 MDN 的说明。它并没有说排序函数不可靠,而是说它不稳定。我理解这可能会令人困惑,但这并不意味着它不能使用。在排序算法的上下文中,“稳定”一词有着特定的含义 - 即“相等”的元素按照输入中的顺序排序。这与代码不稳定(即尚未准备好使用)的概念完全无关。 - Stobor
3
如果您想按特定字符串值排序,例如按城市排序,则可以使用以下代码: this.homes.sort((current,next)=>{ return current.city.localeCompare(next.city)}); 该代码会将原数组按照城市名称进行升序排列。 - Jorge Valvert
显示剩余7条评论

734

这里有一个更加灵活的版本,它允许您创建可重用的排序函数,并按任何字段进行排序。

const sort_by = (field, reverse, primer) => {

  const key = primer ?
    function(x) {
      return primer(x[field])
    } :
    function(x) {
      return x[field]
    };

  reverse = !reverse ? 1 : -1;

  return function(a, b) {
    return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
  }
}


//Now you can sort by any field at will...

const 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:"5",city:"New York",state:"NY",zip:"00010",price:"962500"}];

// Sort by price high to low
console.log(homes.sort(sort_by('price', true, parseInt)));

// Sort by city, case-insensitive, A-Z
console.log(homes.sort(sort_by('city', false, (a) =>  a.toUpperCase()
)));


7
你误读了代码。sort_by 的时间复杂度是 O(1),并返回一个函数,用于在列表中比较项目的内置排序(O(N log N))。总的时间复杂度为 O(n log n) * O(1),简化为 O(n log n),与快速排序相同。 - Kenan Banks
4
一个小的改进:var key = primer ? function(x) { return primer(x[field]); } : function(x) { return x[field]; } - ErikE
11
虽然[1,-1][+!!reverse]看起来很酷,但这是一件可怕的事情。如果用户不能正确调用您的方法,请惩罚他,而不是试图以任何方式强制使其有意义。无论如何。 - Ingo Bürk
2
准备源数据会更好,这样可以避免在明显需要进行一些调整的情况下进行连续解析。 - Gerrit Brink
1
我发现将其添加到Object原型中非常有用,这样你就可以轻松地在任何对象上使用它:Object.prototype.sort_by = function(field,reverse,primer) { var sort_by = function(field, reverse, primer){ var key = primer ? function(x) {return primer(x[field])} : function(x) {return x[field]}; reverse = !reverse ? 1 : -1; return function (a, b) { return a = key(a), b = key(b), reverse * ((a > b) - (b > a)); } } return this.sort(sort_by(field,reverse,primer)) } - MatFiz
显示剩余4条评论

151
要进行排序,您需要创建一个带有两个参数的比较函数。然后按以下方式使用该比较函数调用sort函数:
// a and b are object elements of your array
function mycomparator(a,b) {
  return parseInt(a.price, 10) - parseInt(b.price, 10);
}
homes.sort(mycomparator);

如果你想进行升序排序,请交换减号两侧的表达式。


4
这是一个实际解释该主题的参考资料,而不是简单地说“它太复杂了,你无论如何也不会理解它”:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort - Roland Illig
parseInt(a.price, 10) equivalent parseInt(a.price) same as ~~a.price - a55

85

如果有人需要对字符串进行排序,可以使用以下代码:

const dataArr = {

  "hello": [{
    "id": 114,
    "keyword": "zzzzzz",
    "region": "Sri Lanka",
    "supportGroup": "administrators",
    "category": "Category2"
  }, {
    "id": 115,
    "keyword": "aaaaa",
    "region": "Japan",
    "supportGroup": "developers",
    "category": "Category2"
  }]

};
const sortArray = dataArr['hello'];

console.log(sortArray.sort((a, b) => {
  if (a.region < b.region)
    return -1;
  if (a.region > b.region)
    return 1;
  return 0;
}));


返回 -1; 和返回 1; 有什么含义? - Sara Dina
3
这应该放在顶部,每个人都在谈论对数字进行排序,却没有人谈论按字母表顺序对字母或单词进行排序。谢谢。 - Emeka Orji

54

如果您使用符合ES6标准的浏览器,您可以使用以下功能:

升序和降序排序的区别在于您的比较函数返回值的符号:

var ascending = homes.sort((a, b) => Number(a.price) - Number(b.price));
var descending = homes.sort((a, b) => Number(b.price) - Number(a.price));

这里是一个可用的代码片段:

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": "5",
  "city": "New York",
  "state": "NY",
  "zip": "00010",
  "price": "962500"
}];

homes.sort((a, b) => Number(a.price) - Number(b.price));
console.log("ascending", homes);

homes.sort((a, b) => Number(b.price) - Number(a.price));
console.log("descending", homes);


27
我推荐GitHub: Array sortBy - 这是一个最好的sortBy方法实现,它使用Schwartzian transform
但是现在我们将尝试这种方法Gist: sortBy-old.js
让我们创建一个函数来对数组进行排序,能够按某个属性排序对象。

创建排序函数

var sortBy = (function () {
  var toString = Object.prototype.toString,
      // default parser function
      parse = function (x) { return x; },
      // gets the item to be sorted
      getItem = function (x) {
        var isObject = x != null && typeof x === "object";
        var isProp = isObject && this.prop in x;
        return this.parser(isProp ? x[this.prop] : x);
      };
      
  /**
   * Sorts an array of elements.
   *
   * @param  {Array} array: the collection to sort
   * @param  {Object} cfg: the configuration options
   * @property {String}   cfg.prop: property name (if it is an Array of objects)
   * @property {Boolean}  cfg.desc: determines whether the sort is descending
   * @property {Function} cfg.parser: function to parse the items to expected type
   * @return {Array}
   */
  return function sortby (array, cfg) {
    if (!(array instanceof Array && array.length)) return [];
    if (toString.call(cfg) !== "[object Object]") cfg = {};
    if (typeof cfg.parser !== "function") cfg.parser = parse;
    cfg.desc = !!cfg.desc ? -1 : 1;
    return array.sort(function (a, b) {
      a = getItem.call(cfg, a);
      b = getItem.call(cfg, b);
      return cfg.desc * (a < b ? -1 : +(a > b));
    });
  };
  
}());

设置未排序数据

var data = [
  {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90,  tip: 0,   type: "Tab"},
  {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
  {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0,   type: "cash"},
  {date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"},
  {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
  {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90,  tip: 0,   type: "tab"},
  {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0,   type: "Cash"}
];

使用它

将数组按 "date" 作为 String 排列

// sort by @date (ascending)
sortBy(data, { prop: "date" });

// expected: first element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

如果您想忽略大小写,可以设置parser回调函数:

// sort by @type (ascending) IGNORING case-sensitive
sortBy(data, {
    prop: "type",
    parser: (t) => t.toUpperCase()
});

// expected: first element
// { date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "Cash" }

// expected: last element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa" }

如果您想将"date"字段转换为Date类型:
// sort by @date (descending) AS Date object
sortBy(data, {
    prop: "date",
    desc: true,
    parser: (d) => new Date(d)
});

// expected: first element
// { date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "Visa"}

// expected: last element
// { date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab" }

在这里,您可以与代码进行互动:jsbin.com/lesebi

感谢@Ozesh的反馈,已修复与具有falsy值属性相关的问题。


如果你正在对数字进行排序并且在对象数组中遇到了一个'0',你可能会注意到上面的代码会出错。以下是一个快速修复的方法:var checkNaN = function (value) { return Number.isNaN(Number(value)) ? 0 : value; }然后是: return function (array, o) { .... a = _getItem.call(o, a); a = checkNaN(a);b = _getItem.call(o, b); b = checkNaN(b); return o.desc * (a < b ? -1 : +(a > b)); }); - Ozesh

26

您想要在Javascript中对其进行排序,是吗?您需要的是 sort() 函数。在这种情况下,您需要编写一个比较函数并将其传递给 sort(),类似于以下代码:

function comparator(a, b) {
    return parseInt(a["price"], 10) - parseInt(b["price"], 10);
}

var json = { "homes": [ /* your previous data */ ] };
console.log(json["homes"].sort(comparator));

你的比较器会取出数组中每个嵌套哈希表的其中之一,并通过检查其中的"price"字段来决定哪一个更高。


22

使用lodash.sortBy,(使用commonjs指令,您也可以将cdn的script include标签放在html的顶部)

var sortBy = require('lodash.sortby');
// or
sortBy = require('lodash').sortBy;

降序排列

var descendingOrder = sortBy( homes, 'price' ).reverse();

升序排列

var ascendingOrder = sortBy( homes, 'price' );

1
或者 const sortBy = require('lodash/sortBy'); let calendars = sortBy(calendarListResponse.items, cal => cal.summary); - mpen
不确定loadash最近是否有更改,现在它被命名为OrderByimport { orderBy } from 'lodash'; ... ... return orderBy ( rows, 'fieldName' ).reverse(); - montelof

19

我来晚了,但以下是我的排序逻辑。

function getSortedData(data, prop, isAsc) {
    return data.sort((a, b) => {
        return (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1)
    });
}

2
这个答案最容易理解。我为我的使用情况进行了简化。 function objsort(obj,prop){ return obj.sort( (a, b) => a[prop].toString().localeCompare(b[prop]) ); } - Ken H

15
你可以使用 string1.localeCompare(string2) 来进行字符串比较。
this.myArray.sort((a,b) => { 
    return a.stringProp.localeCompare(b.stringProp);
});

请注意,localCompare 不区分大小写。


请注意,localCompare 现在具有选项,如果您想要区分大小写(和其他选项),则可以使用它。几乎所有最新浏览器都支持此功能。 - ToolmakerSteve
字符串数组排序的最佳解决方案 - Hugo Sohm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接