从这个最初的问题,我将如何在多个字段应用排序?
使用这种稍作调整的结构,我将如何排序城市(上升)和价格(下降)?
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"}
];
我喜欢的事实是,给出的答案提供了一个一般的方法。在我计划使用这段代码的地方,我将不得不对日期以及其他东西进行排序。“启动”对象的能力似乎很方便,如果不是有点麻烦的话。
我试图把这个答案构建成一个很好的通用示例,但我运气不太好。
只需遵循排序标准列表
即使要封装36个排序标准,这段代码也将始终保持可读和可理解
Nina在这里提出的解决方案当然非常优雅,但它意味着要知道在布尔逻辑中,值为0对应的值为false,并且布尔测试在JavaScript中可以返回除true / false以外的值(这里是数值),这对于初学者来说总是令人困惑。
还要考虑谁需要维护您的代码。也许会是你:想象一下你自己花了几天的时间在另一个人的代码上,然后有了一个有害的错误……你读了几千行充满技巧的文章,都累坏了
const 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' }
]
const fSort = (a,b) =>
{
let Dx = a.city.localeCompare(b.city) // 1st criteria
if (Dx===0) Dx = Number(b.price) - Number(a.price) // 2nd
// if (Dx===0) Dx = ... // 3rd
// if (Dx===0) Dx = ... // 4th....
return Dx
}
console.log( homes.sort(fSort))
下面是一种可扩展的按多个字段排序的方法。
homes.sort(function(left, right) {
var city_order = left.city.localeCompare(right.city);
var price_order = parseInt(left.price) - parseInt(right.price);
return city_order || -price_order;
});
笔记
A function passed to array sort is expected to return negative, zero, positive to indicate less, equal, greater.
a.localeCompare(b) is universally supported for strings, and returns -1,0,1 if a<b,a==b,a>b.
Subtraction works on numeric fields, because a - b gives -,0,+ if a<b,a==b,a>b.
|| in the last line gives city priority over price.
Negate to reverse order in any field, as in -price_order
Add new fields to the or-chain: return city_order || -price_order || date_order;
Date compare with subtraction, because date math converts to milliseconds since 1970.var date_order = new Date(left.date) - new Date(right.date);
Boolean compare with subtraction, which is guaranteed to turn true and false to 1 and 0 (therefore the subtraction produces -1 or 0 or 1). var goodness_order = Boolean(left.is_good) - Boolean(right.is_good)This is unusual enough that I'd suggest drawing attention with the Boolean constructor, even if they're already boolean.
哇,这里有一些复杂的解。如此复杂,我决定想出一些更简单但也相当强大的东西。在这里;
function sortByPriority(data, priorities) {
if (priorities.length == 0) {
return data;
}
const nextPriority = priorities[0];
const remainingPriorities = priorities.slice(1);
const matched = data.filter(item => item.hasOwnProperty(nextPriority));
const remainingData = data.filter(item => !item.hasOwnProperty(nextPriority));
return sortByPriority(matched, remainingPriorities)
.sort((a, b) => (a[nextPriority] > b[nextPriority]) ? 1 : -1)
.concat(sortByPriority(remainingData, remainingPriorities));
}
这里有一个如何使用它的例子。
const data = [
{ id: 1, mediumPriority: 'bbb', lowestPriority: 'ggg' },
{ id: 2, highestPriority: 'bbb', mediumPriority: 'ccc', lowestPriority: 'ggg' },
{ id: 3, mediumPriority: 'aaa', lowestPriority: 'ggg' },
];
const priorities = [
'highestPriority',
'mediumPriority',
'lowestPriority'
];
const sorted = sortByPriority(data, priorities);
这将首先根据属性的优先级排序,然后根据属性的值进行排序。