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)
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)
我不建议更改本机对象原型,只是为了给出一个示例,以便您可以在自己的对象上实现它(对于支持它的环境,您也可以使用Object.defineProperty,如下一节所示,至少没有可枚举的负面副作用,如最后一部分所述)
原型实现将类似于以下(这是一个工作示例):
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple.apply(null, args));
}
}
Run Code Online (Sandbox Code Playgroud)
如果你的目标是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.
Vla*_*den 336
在ES6/ES2015或更高版本中,您可以这样做:
objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));
Run Code Online (Sandbox Code Playgroud)
Dav*_*row 185
使用下划线,它小而且很棒......
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)
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)
交换运算符以按反向字母顺序排序.
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)
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)
更新:不再修改原始数组.
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)
Sat*_*pta 30
sort方法可以修改该sort方法以使用比较函数对数字数组、字符串甚至对象等任何内容进行排序。
比较函数作为可选参数传递给排序方法。
该比较函数接受 2 个参数,通常称为a和b。基于这两个参数,您可以修改排序方法以按您想要的方式工作。
sort()方法将a排序为比b更低的索引。简单地说,a 将出现在 b 之前。sort()方法将元素位置保持原样。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
您可以使用
(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)
Nic*_*lle 23
最好不要为每一个简单的逻辑片段添加一个框架,但依靠经过良好测试的实用程序框架,加快开发速度并减少写入的错误数量并不是一件容易的事.
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
我没有看到这种特殊方法的建议,所以这里是一个简洁的比较方法我喜欢使用它适用于string和number:
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)
更新:不工作总是,所以它是不正确的:(
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 将导致正确的输出
另一种选择是使用>=运算符而不是>
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。
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
由于您可能会遇到更复杂的数据结构,例如此数组,我会扩展解决方案.
更可插拔的版本基于@ 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的工作示例
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()'在比较字符串时防止错误是必要的.
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)
一个简单的函数,用于按属性对对象数组进行排序
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)
根据您的示例,您需要按两个字段(姓氏,名字)排序,而不是一个.您可以使用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)
您可以使用可重用的排序功能。
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 中的Array和Object进行排序
。
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)
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)
鉴于原始示例:
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;这是一个简单的问题,不知道为什么人们有这么复杂的解决方案.
一个简单的排序函数(基于快速排序算法):
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)
使用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)
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)
使用 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)
我只是增强了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
// 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 对象数组进行排序
方式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)
这个对我有用。这里 它将保持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)
简单回答:
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:
我已经在各种项目中使用了这个实用程序,并且效果很好。它也非常模块化:
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 次 |
| 最近记录: |