按值对对象属性进行排序

1008

如果我有一个 JavaScript 对象,例如:

var list = {
  "you": 100, 
  "me": 75, 
  "foo": 116, 
  "bar": 15
};

有没有一种方法可以根据值对属性进行排序?这样我最后会得到:

list = {
  "bar": 15, 
  "me": 75, 
  "you": 100, 
  "foo": 116
};

5
不仅要"排序",更重要的是对数字进行排序。数字不受Javascript的Array.sort()方法影响,这意味着你不仅需要找到一种对属性进行排序的方法,还需要编写自己的函数来比较数值大小。 - Sampson
237
在阅读答案之前:答案是否定的。ECMAScript 中对象属性的顺序是非标准的。您不应该对 JavaScript 对象中元素的顺序做出任何假设。对象是一个无序的属性集合。下面的答案向您展示了如何“使用”已排序的属性,借助于数组的帮助,但实际上从未改变对象本身的属性顺序。所以,不,这是不可能的。即使您构建了具有预排序属性的对象,也不能保证它们将来会以相同的顺序显示。请继续阅读 :)。 - Govind Rai
11
在实际的前端应用程序中,我们使用对象集合的 ID 作为键来循环遍历,并且如果转换为 HTML 模板,则顺序很重要。你说它们没有顺序,我说当我在当前浏览器中使用 console.logging 查看它们时,它们确实有顺序。而且这个顺序可能会被重新排序。一旦你循环遍历它们,它们就会有一个顺序。 - ProblemsOfSumit
9
现在规范中有一种方式可以按指定顺序访问属性。这是一个好主意吗?几乎肯定不是。 :-) 但是它已经存在于ES2015中。 - T.J. Crowder
21
2019年的访客们,可以查看这个仅得到少量赞同的基于Object.entries的答案,它是自ES2017以来最干净、最易读的现代方法:https://dev59.com/LXNA5IYBdhLWcg3wKacx#37607084 - jakub.g
显示剩余5条评论
45个回答

9

不使用多个for循环进行值排序(如果按键排序,则在排序回调中更改索引为“0”)

const list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
  };

let sorted = Object.fromEntries(
                Object.entries(list).sort( (a,b) => a[1] - b[1] )    
             ) 
console.log('Sorted object: ', sorted) 


9
非常简短和简单!
var sortedList = {};
Object.keys(list).sort((a,b) => list[a]-list[b]).forEach((key) => {
    sortedList[key] = list[key]; });

8

使用Underscore.js或Lodash.js进行高级数组或对象排序

var data = {
  "models": {

    "LTI": [
      "TX"
    ],
    "Carado": [
      "A",
      "T",
      "A(пасс)",
      "A(груз)",
      "T(пасс)",
      "T(груз)",
      "A",
      "T"
    ],
    "SPARK": [
      "SP110C 2",
      "sp150r 18"
    ],
    "Autobianchi": [
      "A112"
    ]
  }
};

var arr = [],
  obj = {};
for (var i in data.models) {
  arr.push([i, _.sortBy(data.models[i], function(el) {
    return el;
  })]);
}
arr = _.sortBy(arr, function(el) {
  return el[0];
});
_.map(arr, function(el) {
  return obj[el[0]] = el[1];
});
console.log(obj);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js" integrity="sha256-qXBd/EfAdjOA2FGrGAG+b3YBn2tn5A6bhz+LSgYD96k=" crossorigin="anonymous"></script>


5

我正在按照slebetman提供的解决方案(请阅读获取所有细节)进行操作,但进行了调整,因为您的对象是非嵌套的。

// First create the array of keys/values so that we can sort it:
var sort_array = [];
for (var key in list) {
    sort_array.push({key:key,value:list[key]});
}

// Now sort it:
sort_array.sort(function(x,y){return x.value - y.value});

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
    var item = list[sort_array[i].key];

    // now do stuff with each item
}

4

按属性值对对象排序

const obj = { you: 100, me: 75, foo: 116, bar: 15 };
const keysSorted = Object.keys(obj).sort((a, b) => obj[a] - obj[b]);
const result = {};
keysSorted.forEach(key => { result[key] = obj[key]; });
document.write('Result: ' + JSON.stringify(result));

期望的输出:

{"bar":15,"me":75,"you":100,"foo":116}

参考资料:


4
感谢@orad在TypeScript中提供的答案,现在我们可以在JavaScript中使用下面的代码片段。

function sort(obj,valSelector) {
  const sortedEntries = Object.entries(obj)
    .sort((a, b) =>
      valSelector(a[1]) > valSelector(b[1]) ? 1 :
      valSelector(a[1]) < valSelector(b[1]) ? -1 : 0);
  return new Map(sortedEntries);
}

const Countries = { "AD": { "name": "Andorra", }, "AE": { "name": "United Arab Emirates", }, "IN": { "name": "India", }} 

// Sort the object inside object. 
var sortedMap = sort(Countries, val => val.name); 
// Convert to object. 
var sortedObj = {}; 
sortedMap.forEach((v,k) => { sortedObj[k] = v }); console.log(sortedObj); 

//Output: {"AD": {"name": "Andorra"},"IN": {"name": "India"},"AE": {"name": "United Arab Emirates"}}


4

有许多方法可以做到这一点,但由于我没有看到任何使用reduce()的方法,所以在这里放置它。 对某些人来说可能似乎很实用。

var list = {
    "you": 100,
    "me": 75,
    "foo": 116,
    "bar": 15
};

let result = Object.keys(list).sort((a,b)=>list[a]>list[b]?1:-1).reduce((a,b)=> {a[b]=list[b]; return a},{});

console.log(result);


4
let toSort = {a:2323, b: 14, c: 799} 
let sorted = Object.entries(toSort ).sort((a,b)=> a[1]-b[1]) 

输出:

[ [ "b", 14 ], [ "c", 799 ], [ "a", 2323 ] ]

3

如果有人想要保留对象(包括键和值),可以使用@Markus R和@James Moran评论中提供的代码参考,只需使用以下代码:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var newO = {};
Object.keys(list).sort(function(a,b){return list[a]-list[b]})
                 .map(key => newO[key] = list[key]);
console.log(newO);  // {bar: 15, me: 75, you: 100, foo: 116}

2
你正在使用 map 返回一个赋值,使用 forEach 会更好。 - DiegoRBaquero

3
这可能是处理实际有序对象的简单方法。不确定速度有多慢,同时使用while循环可能更好。
Object.sortByKeys = function(myObj){
  var keys = Object.keys(myObj)
  keys.sort()
  var sortedObject = Object()
  for(i in keys){
    key = keys[i]
    sortedObject[key]=myObj[key]
   }

  return sortedObject

}

然后我从这里找到了这个反转函数: http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/

Object.invert = function (obj) {

  var new_obj = {};

  for (var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      new_obj[obj[prop]] = prop;
    }
  }

  return new_obj;
};

So

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var invertedList = Object.invert(list)
var invertedOrderedList = Object.sortByKeys(invertedList)
var orderedList = Object.invert(invertedOrderedList)

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