按字符串属性值对对象数组进行排序
- 2024-11-02 20:49:00
- admin 原创
- 37
问题描述:
我有一个 JavaScript 对象数组:
var objs = [
{ first_nom: 'Laszlo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
我如何根据last_nom
JavaScript 中的值对它们进行排序?
我知道sort(a,b)
,但这似乎只适用于字符串和数字。我需要toString()
向对象添加方法吗?
解决方案 1:
编写自己的比较函数非常简单:
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
解决方案 2:
您还可以创建一个动态排序函数,根据您传递的值对对象进行排序:
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"));
其实这已经回答了这个问题。下面部分是因为很多人联系我,抱怨它不适用于多个参数。
多个参数
您可以使用下面的函数来生成具有多个排序参数的排序函数。
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");
解决方案 3:
在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)
});
解决方案 4:
Underscore.js
使用 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');
解决方案 5:
区分大小写
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: 'Pirate', last_nom: 'Prentice' }
];
// Define a couple of sorting callback functions, one with hardcoded sort key and the other with an argument sort key
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("Using sorter1 - Hardcoded sort property last_name", objs);
objs.sort(sorter2('first_nom'));
console.log("Using sorter2 - passed param sortBy='first_nom'", objs);
objs.sort(sorter2('last_nom'));
console.log("Using sorter2 - passed param sortBy='last_nom'", objs);
运行代码片段Hide results展开片段
解决方案 6:
如果您有重复的姓氏,您可以按名字排序 -
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;
});
解决方案 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;
});
解决方案 8:
使用原型继承可以简单快速地解决这个问题:
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"}]
更新:不再修改原始数组。
解决方案 9:
不正确的旧答案:
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`
解决方案 10:
您可以使用最简单的方法:Lodash
(https://lodash.com/docs/4.17.10#orderBy)
此方法与此类似_.sortBy
,不同之处在于它允许指定迭代器的排序顺序。如果未指定顺序,则所有值均按升序排序。否则,指定“desc”以表示降序,或指定“asc”以表示相应值的升序排序。
参数
collection (Array|Object):要迭代的集合。[iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]):要排序的迭代器。[orders] (string[]):迭代器的排序顺序。
返回
(数组):返回新的排序数组。
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']);
解决方案 11:
Lodash (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
来指定应匹配的属性的路径。我们将按嵌套的 age 属性对用户对象进行排序。是的,它允许嵌套属性匹配!
const sortedObjs = _.sortBy(users, ['user.age']);
想要反转吗?没问题。使用_.reverse。
const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));
想要使用链条将两者结合起来吗?
const { chain } = require('lodash');
const sortedObjs = chain(users).sortBy('user.age').reverse().value();
或者什么时候您更喜欢流程而不是链式?
const { flow, reverse, sortBy } = require('lodash/fp');
const sortedObjs = flow([sortBy('user.age'), reverse])(users);
解决方案 12:
我还没有看到建议这种特殊的方法,因此这里有一个我喜欢使用的简洁的比较方法,它适用于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 => {
const cmp = (a, b) => -(a < b) || +(a > b);
return (a, b) => cmp(fn(a), fn(b));
};
const getLastName = o => o.last_nom;
const sortByLastName = sortBy(getLastName);
objs.sort(sortByLastName);
console.log(objs.map(getLastName));
运行代码片段Hide results展开片段
解释sortBy()
sortBy()
接受一个fn
,它从对象中选择一个值用于比较,并返回一个可以传递给的函数Array.prototype.sort()
。在这个例子中,我们正在比较o.last_nom
。每当我们收到两个对象,例如
a = { first_nom: 'Lazslo', last_nom: 'Jamf' }
b = { first_nom: 'Pig', last_nom: 'Bodine' }
我们将它们与进行比较(a, b) => cmp(fn(a), fn(b))
。鉴于
fn = o => o.last_nom
我们可以将比较函数扩展为(a, b) => cmp(a.last_nom, b.last_nom)
。由于JavaScript 中逻辑 OR ( ||
) 的工作方式,cmp(a.last_nom, b.last_nom)
因此相当于
if (a.last_nom < b.last_nom) return -1;
if (a.last_nom > b.last_nom) return 1;
return 0;
顺便说一下,在其他语言中,这被称为三向比较“宇宙飞船”(<=>
)运算符。
最后,这是不使用箭头函数的 ES5 兼容语法:
显示代码片段
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
function sortBy(fn) {
function cmp(a, b) { return -(a < b) || +(a > b); }
return function (a, b) { return cmp(fn(a), fn(b)); };
}
function getLastName(o) { return o.last_nom; }
var sortByLastName = sortBy(getLastName);
objs.sort(sortByLastName);
console.log(objs.map(getLastName));
Run code snippetHide resultsExpand snippet
解决方案 13:
除了使用自定义比较函数之外,您还可以创建具有自定义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();
解决方案 14:
这里有很多不错的答案,但我想指出的是,它们可以非常简单地扩展以实现更复杂的排序。您唯一要做的就是使用 OR 运算符链接比较函数,如下所示:
objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )
其中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) )
分为两个步骤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) )
通用比较函数可能是这样的:
// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])
此函数可以扩展以支持数字字段、区分大小写、任意数据类型等。
您可以按排序优先级链接它们来使用它们:
// 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") )
这里的重点是,纯 JavaScript 和函数式方法可以让你无需外部库或复杂代码就能取得很大进展。它也非常有效,因为不需要进行字符串解析。
解决方案 15:
尝试一下:
最高至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;
});
在ES6及更高版本中
// Ascending sort
items.sort((a, b) => a.value - b.value);
// Descending sort
items.sort((a, b) => b.value - a.value);
解决方案 16:
使用 JavaScriptsort
方法
可以修改该sort
方法以使用比较函数对任何内容(例如数字数组、字符串甚至对象)进行排序。
比较函数作为可选参数传递给排序方法。
此比较函数接受 2 个参数,通常称为a和b。根据这两个参数,您可以修改排序方法以根据需要工作。
如果比较函数返回小于 0,则该
sort()
方法将a排序在比b更低的索引处。简单来说,a 将排在 b 之前。如果比较函数返回等于 0,则该
sort()
方法保留元素位置不变。如果比较函数返回大于 0,则该
sort()
方法将a排序在比b更大的索引处。简单来说,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)
运行代码片段Hide results展开片段
解决方案 17:
用法示例:
objs.sort(sortBy('last_nom'));
脚本:
/**
* @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;
};
};
解决方案 18:
编写简短代码:
objs.sort((a, b) => a.last_nom > b.last_nom ? 1 : -1)
解决方案 19:
我没有看到任何与我的类似的实现。此版本基于Schwartzian 变换习语。
function sortByAttribute(array, ...attrs) {
// Generate an array of predicate-objects containing
// 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);
}
下面是一个如何使用它的示例:
let games = [
{ name: 'Mashraki', 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'));
解决方案 20:
当您想要进行自然字符串排序(即)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);
运行代码片段Hide results展开片段
注意:的undefined
构造函数参数Intl.Collator
代表语言环境,可以是明确的 ISO 639-1 语言代码(例如)en
,也可以是系统默认语言环境(当)undefined
。
浏览器支持Intl.Collator
解决方案 21:
对(更多)复杂对象数组进行排序
由于您可能会遇到像此数组一样更复杂的数据结构,因此我会扩展解决方案。
总结
根据@ege-Özcan非常可爱的回答,有更多的可插入版本。
问题
我遇到了下面的情况,无法更改。我也不想暂时将对象扁平化。我也不想使用 underscore / lodash,主要是出于性能原因和自己实现的乐趣。
var People = [
{Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
{Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
{Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];
目标
目标是主要按照以下方式进行排序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;
}
}
例子
JSBin 上的工作示例
解决方案 22:
将 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));
}
Usage:
// 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");
运行代码片段Hide results展开片段
解决方案 23:
还有一个选择:
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));
它默认按升序排序。
解决方案 24:
一个简单的方法:
objs.sort(function(a,b) {
return b.last_nom.toLowerCase() < a.last_nom.toLowerCase();
});
请参阅'.toLowerCase()'
有必要防止在比较字符串时出现错误。
解决方案 25:
警告!不建议
使用此解决方案,因为它不会产生排序数组。它留在这里以供将来参考,因为这个想法并不罕见。
objs.sort(function(a,b){return b.last_nom>a.last_nom})
解决方案 26:
这是我的看法:
该order
参数是可选的,默认为“ASC”,表示升序。
它适用于重音字符并且不区分大小写。
注意:它排序并返回原始数组。
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;
}
片段
function sanitizeToSort(str) {
return str
.normalize('NFD') // Remove accented characters
.replace(/[/u0300-/u036f]/g, '') // Remove diacritics
.toLowerCase()
;
}
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;
}
const rockStars = [
{ name: "Axl",
lastname: "Rose" },
{ name: "Elthon",
lastname: "John" },
{ name: "Paul",
lastname: "McCartney" },
{ name: "Lou",
lastname: "Reed" },
{ name: "freddie", // Works on lower/upper case
lastname: "mercury" },
{ name: "Ámy", // Works on accented characters too
lastname: "winehouse"}
];
sortByProperty(rockStars, "name");
console.log("Ordered by name A-Z:");
rockStars.forEach((item) => console.log(item.name + " " + item.lastname));
sortByProperty(rockStars, "lastname", "DESC");
console.log("
Ordered by lastname Z-A:");
rockStars.forEach((item) => console.log(item.lastname + ", " + item.name));
运行代码片段Hide results展开片段
解决方案 27:
给出原始示例:
var objs = [
{ first_nom: 'Lazslo', last_nom: 'Jamf' },
{ first_nom: 'Pig', last_nom: 'Bodine' },
{ first_nom: 'Pirate', last_nom: 'Prentice' }
];
按多个字段排序:
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;
});
笔记
a.localeCompare(b)
得到普遍支持a<b
,如果,a==b
,分别返回 -1,0,1a>b
。||
最后一行的last_nom
优先于first_nom
。减法适用于数值字段:
var age_order = left.age - right.age;
否定以反转顺序,
return -last_nom_order || -first_nom_order || -age_order;
解决方案 28:
根据属性对对象数组进行排序的简单函数:
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
}
用法:
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
解决方案 29:
Ege Özcan 代码的附加描述参数:
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;
}
}
解决方案 30:
您可能需要将它们转换为小写形式以避免混淆。
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
})
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件