按属性值排序对象
Posted
技术标签:
【中文标题】按属性值排序对象【英文标题】:Sorting objects by property values 【发布时间】:2011-01-28 19:27:03 【问题描述】:如何仅使用 javascript 实现以下场景:
创建具有属性(最高速度、品牌等)的汽车对象 对按这些属性排序的汽车列表进行排序【问题讨论】:
@durilai: JavaScript 是面向对象的,JavaScript 的 OO 模型基于 Prototyping 并且非常非常通用...@987654321 @ 我推荐使用 lodash.js :lodash.com/docs#sortBy 【参考方案1】:这是一个简短的示例,它创建对象数组,并按数字或字母顺序排序:
// Create Objects Array
var arrayCarObjects = [
brand: "Honda", topSpeed: 45,
brand: "Ford", topSpeed: 6,
brand: "Toyota", topSpeed: 240,
brand: "Chevrolet", topSpeed: 120,
brand: "Ferrari", topSpeed: 1000
];
// Sort Objects Numerically
arrayCarObjects.sort((a, b) => (a.topSpeed - b.topSpeed));
// Sort Objects Alphabetically
arrayCarObjects.sort((a, b) => (a.brand > b.brand) ? 1 : -1);
【讨论】:
【参考方案2】:使用 ES6 箭头函数会是这样的:
//Let's say we have these cars
let cars = [ brand: 'Porsche', top_speed: 260 ,
brand: 'Benz', top_speed: 110 ,
brand: 'Fiat', top_speed: 90 ,
brand: 'Aston Martin', top_speed: 70 ]
Array.prototype.sort()
可以接受比较器函数(这里我使用了箭头符号,但普通函数的工作方式相同):
let sortedByBrand = [...cars].sort((first, second) => first.brand > second.brand)
// [ brand: 'Aston Martin', top_speed: 70 ,
// brand: 'Benz', top_speed: 110 ,
// brand: 'Fiat', top_speed: 90 ,
// brand: 'Porsche', top_speed: 260 ]
上述方法将汽车数组的内容复制到一个新数组中,并根据品牌名称按字母顺序对其进行排序。同样,您可以传递不同的函数:
let sortedBySpeed =[...cars].sort((first, second) => first.top_speed > second.top_speed)
//[ brand: 'Aston Martin', top_speed: 70 ,
// brand: 'Fiat', top_speed: 90 ,
// brand: 'Benz', top_speed: 110 ,
// brand: 'Porsche', top_speed: 260 ]
如果您不介意改变原始数组 cars.sort(comparatorFunction)
就可以了。
【讨论】:
【参考方案3】:假设我们必须根据特定属性按升序对对象列表进行排序,在此示例中假设我们必须根据“名称”属性进行排序,那么下面是所需的代码:
var list_Objects = ["name"="Bob","name"="Jay","name"="Abhi"];
Console.log(list_Objects); //["name"="Bob","name"="Jay","name"="Abhi"]
list_Objects.sort(function(a,b)
return a["name"].localeCompare(b["name"]);
);
Console.log(list_Objects); //["name"="Abhi","name"="Bob","name"="Jay"]
【讨论】:
我想你有错字?返回 a["name"].localeCompare(b.["name"]);应该返回 a["name"].localeCompare(b["name"]); (去掉 b 之后的 .)【参考方案4】:我为自己编写了这个简单的函数:
function sortObj(list, key)
function compare(a, b)
a = a[key];
b = b[key];
var type = (typeof(a) === 'string' ||
typeof(b) === 'string') ? 'string' : 'number';
var result;
if (type === 'string') result = a.localeCompare(b);
else result = a - b;
return result;
return list.sort(compare);
例如,您有汽车列表:
var cars= [brand: 'audi', speed: 240, brand: 'fiat', speed: 190];
var carsSortedByBrand = sortObj(cars, 'brand');
var carsSortedBySpeed = sortObj(cars, 'speed');
【讨论】:
【参考方案5】:一个带有反向排序的 Cheeso 解决方案,由于不清晰,我也删除了三元表达式(但这是个人喜好)。
function(prop, reverse)
return function(a, b)
if (typeof a[prop] === 'number')
return (a[prop] - b[prop]);
if (a[prop] < b[prop])
return reverse ? 1 : -1;
if (a[prop] > b[prop])
return reverse ? -1 : 1;
return 0;
;
;
【讨论】:
要完全反转数字需要return !!reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
是的,因为现在没有反向检查数字,谢谢,我应该解决这个问题。但是为什么双 !
这也很好:return reverse ? (a[prop] - b[prop]) * -1 : (a[prop] - b[prop]);
!!
强制将类型强制转换为本机布尔类型值,而不是 JavaScript 值的“虚假”性质,这不是严格需要的,但至少对我来说澄清了目的。请注意,当您返回带有 !!
的值时,它是本机布尔类型,而不是带有“假”值的本机类型,即 typeof !!undefined
或 typeof !!null
等。返回“布尔”注意@ 987654329@ 是 true
但 !!""
是 false
(空格,字符串中没有空格)但你可能已经知道了。【参考方案6】:
javascript 有 sort 函数,它可以将另一个函数作为参数 - 第二个函数用于比较两个元素。
例子:
cars = [
name: "Honda",
speed: 80
,
name: "BMW",
speed: 180
,
name: "Trabi",
speed: 40
,
name: "Ferrari",
speed: 200
]
cars.sort(function(a, b)
return a.speed - b.speed;
)
for(var i in cars)
document.writeln(cars[i].name) // Trabi Honda BMW Ferrari
好的,从您的评论中,我看到您在错误意义上使用了“排序”一词。在编程中,“排序”的意思是“将事物按一定顺序排列”,而不是“将事物分组排列”。后者要简单得多——这就是你在现实世界中“排序”事物的方式
制作两个空数组(“盒子”) 对于列表中的每个对象,检查它是否符合条件 如果是的话,把它放在第一个“盒子”里 如果没有,则放入第二个“盒子”【讨论】:
为方便起见简单说明:此 (a.someProp - b.someProp
) 从 从低到高 排序,反之 (b.someProp - a.someProp
) 从高到低排序。基本上,if the function returns less than 0, a comes before b.
另请注意,此解决方案仅适用于您排序的属性是数字时。这适用于按最高速度排序的示例,但如果您想按汽车品牌排序,此解决方案不会按字母顺序对字符串进行排序。 Cheeso provides an answer for sorting by both numbers and strings.
另请注意,当数字非常高或非常低时,即减法运算下溢时,排序将不起作用。【参考方案7】:
示例。
这在 cscript.exe 上运行,在 windows 上。
// define the Car class
(function()
// makeClass - By John Resig (MIT Licensed)
// Allows either new User() or User() to be employed for construction.
function makeClass()
return function(args)
if ( this instanceof arguments.callee )
if ( typeof this.init == "function" )
this.init.apply( this, (args && args.callee) ? args : arguments );
else
return new arguments.callee( arguments );
;
Car = makeClass();
Car.prototype.init = function(make, model, price, topSpeed, weight)
this.make = make;
this.model = model;
this.price = price;
this.weight = weight;
this.topSpeed = topSpeed;
;
)();
// create a list of cars
var autos = [
new Car("Chevy", "Corvair", 1800, 88, 2900),
new Car("Buick", "LeSabre", 31000, 138, 3700),
new Car("Toyota", "Prius", 24000, 103, 3200),
new Car("Porsche", "911", 92000, 155, 3100),
new Car("Mercedes", "E500", 67000, 145, 3800),
new Car("VW", "Passat", 31000, 135, 3700)
];
// a list of sorting functions
var sorters =
byWeight : function(a,b)
return (a.weight - b.weight);
,
bySpeed : function(a,b)
return (a.topSpeed - b.topSpeed);
,
byPrice : function(a,b)
return (a.price - b.price);
,
byModelName : function(a,b)
return ((a.model < b.model) ? -1 : ((a.model > b.model) ? 1 : 0));
,
byMake : function(a,b)
return ((a.make < b.make) ? -1 : ((a.make > b.make) ? 1 : 0));
;
function say(s) WScript.Echo(s);
function show(title)
say ("sorted by: "+title);
for (var i=0; i < autos.length; i++)
say(" " + autos[i].model);
say(" ");
autos.sort(sorters.byWeight);
show("Weight");
autos.sort(sorters.byModelName);
show("Name");
autos.sort(sorters.byPrice);
show("Price");
你也可以做一个通用的分拣机。
var byProperty = function(prop)
return function(a,b)
if (typeof a[prop] == "number")
return (a[prop] - b[prop]);
else
return ((a[prop] < b[prop]) ? -1 : ((a[prop] > b[prop]) ? 1 : 0));
;
;
autos.sort(byProperty("topSpeed"));
show("Top Speed");
【讨论】:
以上是关于按属性值排序对象的主要内容,如果未能解决你的问题,请参考以下文章