Sorting JavaScript Object by property value
如果我有一个javascript对象,比如:
1 2 3 4 5 6 | var list = { "you": 100, "me": 75, "foo": 116, "bar": 15 }; |
有没有根据值对属性排序的方法?所以我最终
1 2 3 4 5 6 | list = { "bar": 15, "me": 75, "you": 100, "foo": 116 }; |
将它们移动到一个数组中,对该数组进行排序,然后将该数组用于您的目的。以下是解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var maxSpeed = { car: 300, bike: 60, motorbike: 200, airplane: 1000, helicopter: 400, rocket: 8 * 60 * 60 }; var sortable = []; for (var vehicle in maxSpeed) { sortable.push([vehicle, maxSpeed[vehicle]]); } sortable.sort(function(a, b) { return a[1] - b[1]; }); //[["bike", 60], ["motorbike", 200], ["car", 300], //["helicopter", 400], ["airplane", 1000], ["rocket", 28800]] |
一旦你有了数组,你就可以按照你喜欢的顺序从数组中重建对象,从而实现你所要做的。这在我所知道的所有浏览器中都可以使用,但是它将依赖于一个实现怪癖,并且可以在任何时候中断。您不应该对JavaScript对象中的元素顺序进行假设。
我们不想复制整个数据结构,也不想在需要关联数组的地方使用数组。
以下是另一种与波娜做同样事情的方法:
1 2 3 | var list = {"you": 100,"me": 75,"foo": 116,"bar": 15}; keysSorted = Object.keys(list).sort(function(a,b){return list[a]-list[b]}) console.log(keysSorted); // bar,me,you,foo |
对象可以具有任意数量的属性,如果将对象放入数组中,则可以选择按所需的对象属性、数字或字符串进行排序。考虑这个数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var arrayOfObjects = [ { name: 'Diana', born: 1373925600000, // Mon, Jul 15 2013 num: 4, sex: 'female' }, { name: 'Beyonce', born: 1366832953000, // Wed, Apr 24 2013 num: 2, sex: 'female' }, { name: 'Albert', born: 1370288700000, // Mon, Jun 3 2013 num: 3, sex: 'male' }, { name: 'Doris', born: 1354412087000, // Sat, Dec 1 2012 num: 1, sex: 'female' } ]; |
按出生日期排序,最老的先排序
1 2 3 4 5 6 7 | // use slice() to copy the array and not just make a reference var byDate = arrayOfObjects.slice(0); byDate.sort(function(a,b) { return a.born - b.born; }); console.log('by date:'); console.log(byDate); |
按名称排序
1 2 3 4 5 6 7 8 9 | var byName = arrayOfObjects.slice(0); byName.sort(function(a,b) { var x = a.name.toLowerCase(); var y = b.name.toLowerCase(); return x < y ? -1 : x > y ? 1 : 0; }); console.log('by name:'); console.log(byName); |
http://jsfiddle.net/xsm5s/16/
为了完整起见,此函数返回已排序的对象属性数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function sortObject(obj) { var arr = []; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { arr.push({ 'key': prop, 'value': obj[prop] }); } } arr.sort(function(a, b) { return a.value - b.value; }); //arr.sort(function(a, b) { a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings return arr; // returns array } var list = {"you": 100,"me": 75,"foo": 116,"bar": 15}; var arr = sortObject(list); console.log(arr); // [{key:"bar", value:15}, {key:"me", value:75}, {key:"you", value:100}, {key:"foo", value:116}] |
上面的代码就是这里。此解决方案基于本文。
这里是用于排序字符串的更新小提琴。对于区分大小写的字符串比较,可以从中删除另外两个.toLowercase()转换。
javascript对象的定义是无序的(请参见EcmaScript语言规范,第8.6节)。语言规范甚至不能保证,如果您连续两次迭代一个对象的属性,那么它们第二次将以相同的顺序出现。
如果需要排序,请使用数组和array.prototype.sort方法。
@marcusr答案的"箭头"版本供参考
1 2 3 | var myObj = {"you": 100,"me": 75,"foo": 116,"bar": 15}; keysSorted = Object.keys(myObj).sort((a,b) => myObj[a]-myObj[b]) alert(keysSorted); // bar,me,you,foo |
更新日期:2017年4月-这将返回上面定义的已排序的
1 2 3 4 5 6 7 | Object .keys(myObj) .sort((a, b) => myObj[a]-myObj[b]) .reduce((_sortedObj, key) => ({ ..._sortedObj, [key]: myObj[key] }), {}) |
试试看!
更新:2018年10月-object.entries版本
1 2 3 4 5 6 7 | Object .entries(myObj) .sort() .reduce((_sortedObj, [k,v]) => ({ ..._sortedObj, [k]: v }), {}) |
试试看!
ecmascript 2017推出了
这些特性使得将哈希排序为有序对象变得非常容易。到目前为止,只有一小部分的javascript平台支持它们,但您可以在firefox 47+上尝试。
1 2 3 4 5 6 7 | let obj = {"you": 100,"me": 75,"foo": 116,"bar": 15}; let entries = Object.entries(obj); // [["you",100],["me",75],["foo",116],["bar",15]] let sorted = entries.sort((a, b) => a[1] - b[1]); // [["bar",15],["me",75],["you",100],["foo",116]] |
好的,正如您可能知道的,javascript有sort()函数,用于对数组进行排序,但不用于对象…
因此,在这种情况下,我们需要以某种方式获取键数组并对它们进行排序,这就是API在大多数情况下给数组中的对象提供对象的原因,因为数组使用的本机函数比对象文本更多,无论如何,快速解决方法是使用返回对象键数组的object.key,我在w下面创建es6函数。这项工作是为您完成的,它在javascript中使用原生sort()和reduce()函数:
1 2 3 4 5 6 | function sortObject(obj) { return Object.keys(obj) .sort().reduce((a, v) => { a[v] = obj[v]; return a; }, {}); } |
现在你可以这样使用它:
1 2 | let myObject = {a: 1, c: 3, e: 5, b: 2, d: 4}; let sortedMyObject = sortObject(myObject); |
检查SortedMyObject,您可以看到按如下键排序的结果:
1 | {a: 1, b: 2, c: 3, d: 4, e: 5} |
同样,主对象不会被触摸,我们实际上得到了一个新的对象。
我还创建了下面的图像,以使功能步骤更清晰,以防您需要对其进行一些更改以按您的方式工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | var list = { "you": 100, "me": 75, "foo": 116, "bar": 15 }; function sortAssocObject(list) { var sortable = []; for (var key in list) { sortable.push([key, list[key]]); } // [["you",100],["me",75],["foo",116],["bar",15]] sortable.sort(function(a, b) { return (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0)); }); // [["bar",15],["me",75],["you",100],["foo",116]] var orderedList = {}; for (var idx in sortable) { orderedList[sortable[idx][0]] = sortable[idx][1]; } return orderedList; } sortAssocObject(list); // {bar: 15, me: 75, you: 100, foo: 116} |
用于高级数组或对象排序的underline.js或lodash.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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); |
演示
使用ES6更新:如果您的问题是有一个排序的对象要迭代(这就是为什么我认为您希望对对象属性进行排序),那么您可以使用映射对象。
您可以按排序顺序插入(键、值)对,然后执行
1 2 3 4 5 6 7 8 | var myMap = new Map(); myMap.set(0,"zero"); myMap.set(1,"one"); for (var [key, value] of myMap) { console.log(key +" =" + value); } // 0 = zero // 1 = one |
我遵循slebetman给出的解决方案(阅读它了解所有细节),但是进行了调整,因为您的对象是非嵌套的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 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 } |
为了以防万一,有人想用@markus r和@james moran comment的代码引用来保存对象(带有键和值),只需使用:
16这可能是一种简单的方法,将其作为一个真正有序的对象来处理。不知道有多慢。也可以使用while循环。
1 2 3 4 5 6 7 8 9 10 11 12 | 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/
1 2 3 4 5 6 7 8 9 10 11 12 | Object.invert = function (obj) { var new_obj = {}; for (var prop in obj) { if(obj.hasOwnProperty(prop)) { new_obj[obj[prop]] = prop; } } return new_obj; }; |
所以
1 2 3 4 | 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) |
许多相似和有用的功能:https://github.com/shimondoodkin/groupby函数/
16这里还有一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | function sortObject(obj) { var arr = []; var prop; for (prop in obj) { if (obj.hasOwnProperty(prop)) { arr.push({ 'key': prop, 'value': obj[prop] }); } } arr.sort(function(a, b) { return a.value - b.value; }); return arr; // returns array } var list = { car: 300, bike: 60, motorbike: 200, airplane: 1000, helicopter: 400, rocket: 8 * 60 * 60 }; var arr = sortObject(list); console.log(arr); |
按值排序的对象(DESC)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function sortObject(list) { var sortable = []; for (var key in list) { sortable.push([key, list[key]]); } sortable.sort(function(a, b) { return (a[1] > b[1] ? -1 : (a[1] < b[1] ? 1 : 0)); }); var orderedList = {}; for (var i = 0; i < sortable.length; i++) { orderedList[sortable[i][0]] = sortable[i][1]; } return orderedList; } |
对不带多个for循环的值排序(按键排序,将排序回调中的索引更改为"0")。
1 2 3 4 5 6 7 8 9 10 11 | 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) |
我为此做了一个插件,它接受1个arg,这是一个未排序的对象,并返回一个按prop值排序的对象。这将适用于所有二维对象,如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | var sloppyObj = { 'C': 78, 'A': 3, 'B': 4 }; // Extend object to support sort method function sortObj(obj) { "use strict"; function Obj2Array(obj) { var newObj = []; for (var key in obj) { if (!obj.hasOwnProperty(key)) return; var value = [key, obj[key]]; newObj.push(value); } return newObj; } var sortedArray = Obj2Array(obj).sort(function(a, b) { if (a[1] < b[1]) return -1; if (a[1] > b[1]) return 1; return 0; }); function recreateSortedObject(targ) { var sortedObj = {}; for (var i = 0; i < targ.length; i++) { sortedObj[targ[i][0]] = targ[i][1]; } return sortedObj; } return recreateSortedObject(sortedArray); } var sortedObj = sortObj(sloppyObj); alert(JSON.stringify(sortedObj)); |
下面是按预期工作的函数的演示http://codepen.io/nicholasabrams/pen/rwrqve?编辑= 001
使用查询JS可以这样做
1 2 3 4 5 6 | list.keys().select(function(k){ return { key: k, value : list[k] } }).orderBy(function(e){ return e.value;}); |
您可以在这里找到有关查询JS的介绍性文章
试试这个。即使您的对象没有您尝试排序所基于的属性,也将得到处理。
只需通过发送带有对象的属性来调用它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | var sortObjectByProperty = function(property,object){ console.time("Sorting"); var sortedList = []; emptyProperty = []; tempObject = []; nullProperty = []; $.each(object,function(index,entry){ if(entry.hasOwnProperty(property)){ var propertyValue = entry[property]; if(propertyValue!="" && propertyValue!=null){ sortedList.push({key:propertyValue.toLowerCase().trim(),value:entry}); }else{ emptyProperty.push(entry); } }else{ nullProperty.push(entry); } }); sortedList.sort(function(a,b){ return a.key < b.key ? -1 : 1; //return a.key < b.key?-1:1; // Asc //return a.key < b.key?1:-1; // Desc }); $.each(sortedList,function(key,entry){ tempObject[tempObject.length] = entry.value; }); if(emptyProperty.length>0){ tempObject.concat(emptyProperty); } if(nullProperty.length>0){ tempObject.concat(nullProperty); } console.timeEnd("Sorting"); return tempObject; } |
谢谢,继续回答@nosredna
现在我们了解了需要将对象转换为数组,然后对数组进行排序。这对于按字符串排序数组(或将对象转换为数组)很有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | Object {6: Object, 7: Object, 8: Object, 9: Object, 10: Object, 11: Object, 12: Object} 6: Object id:"6" name:"PhD" obe_service_type_id:"2" __proto__: Object 7: Object id:"7" name:"BVC (BPTC)" obe_service_type_id:"2" __proto__: Object //Sort options var sortable = []; for (var vehicle in options) sortable.push([vehicle, options[vehicle]]); sortable.sort(function(a, b) { return a[1].name < b[1].name ? -1 : 1; }); //sortable => prints [Array[2], Array[2], Array[2], Array[2], Array[2], Array[2], Array[2]] 0: Array[2] 0:"11" 1: Object id:"11" name:"AS/A2" obe_service_type_id:"2" __proto__: Object length: 2 __proto__: Array[0] 1: Array[2] 0:"7" 1: Object id:"7" name:"BVC (BPTC)" obe_service_type_id:"2" __proto__: Object length: 2 |
解决这一问题的另一种方法是:
1 2 3 4 5 6 7 8 9 10 11 12 | var res = [{"s1":5},{"s2":3},{"s3":8}].sort(function(obj1,obj2){ var prop1; var prop2; for(prop in obj1) { prop1=prop; } for(prop in obj2) { prop2=prop; } //the above two for loops will iterate only once because we use it to find the key return obj1[prop1]-obj2[prop2]; }); |
//res将具有结果数组
下面是获取排序对象和返回排序对象的方法
1 2 3 4 5 6 7 | let sortedObject = {} sortedObject = Object.keys(yourObject).sort((a, b) => { return yourObject[a] - yourObject[b] }).reduce((prev, curr, i) => { prev[i] = yourObject[curr] return prev }, {}); |
您可以根据需要定制排序功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var list = { "you": 100, "me": 75, "foo": 116, "bar": 15 }; var tmpList = {}; while (Object.keys(list).length) { var key = Object.keys(list).reduce((a, b) => list[a] > list[b] ? a : b); tmpList[key] = list[key]; delete list[key]; } list = tmpList; console.log(list); // { foo: 116, you: 100, me: 75, bar: 15 } |
1 2 3 4 5 6 7 8 9 | function sortObjByValue(list){ var sortedObj = {} Object.keys(list) .map(key => [key, list[key]]) .sort((a,b) => a[1] > b[1] ? 1 : a[1] < b[1] ? -1 : 0) .forEach(data => sortedObj[data[0]] = data[1]); return sortedObj; } sortObjByValue(list); |
Github Gist链接
上面找不到既有效又小的答案,并且支持嵌套对象(而不是数组),所以我编写了自己的答案:)同时适用于字符串和int。
1 2 3 4 5 6 7 8 | function sortObjectProperties(obj, sortValue){ var keysSorted = Object.keys(obj).sort(function(a,b){return obj[a][sortValue]-obj[b][sortValue]}); var objSorted = {}; for(var i = 0; i < keysSorted.length; i++){ objSorted[keysSorted[i]] = obj[keysSorted[i]]; } return objSorted; } |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* sample object with unsorder properties, that we want to sort by their"customValue" property */ var objUnsorted = { prop1 : { customValue : 'ZZ' }, prop2 : { customValue : 'AA' } } // call the function, passing object and property with it should be sorted out var objSorted = sortObjectProperties(objUnsorted, 'customValue'); // now console.log(objSorted) will return: { prop2 : { customValue : 'AA' }, prop1 : { customValue : 'ZZ' } } |
如果我有这样的东西,
1 2 3 4 5 6 7 | var dayObj = { "Friday":["5:00pm to 12:00am"] , "Wednesday":["5:00pm to 11:00pm"], "Sunday":["11:00am to 11:00pm"], "Thursday":["5:00pm to 11:00pm"], "Saturday":["11:00am to 12:00am"] } |
想按天顺序排序,
我们应该先让Daystermap,
1 2 3 4 5 6 7 8 9 10 | var daySorterMap = { //"sunday": 0, // << if sunday is first day of week "Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 4, "Friday": 5, "Saturday": 6, "Sunday": 7 } |
启动一个单独的SortedDayObj对象,
1 2 3 4 | var sortedDayObj={}; Object.keys(dayObj) .sort((a,b) => daySorterMap[a] - daySorterMap[b]) .forEach(value=>sortedDayObj[value]= dayObj[value]) |
您可以退回SORTEDDAYOBJ
1 2 3 4 5 6 7 8 9 10 11 | a = { b: 1, p: 8, c: 2, g: 1 } Object.keys(a) .sort((c,b) => { return a[b]-a[c] }) .reduce((acc, cur) => { let o = {} o[cur] = a[cur] acc.push(o) return acc } , []) |
输出=[P:8,C:2,B:1,G:1]