从这个最初的问题,我将如何在多个字段应用排序?
使用这种稍作调整的结构,我将如何排序城市(上升)和价格(下降)?
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"}
];
我喜欢的事实是,给出的答案提供了一个一般的方法。在我计划使用这段代码的地方,我将不得不对日期以及其他东西进行排序。“启动”对象的能力似乎很方便,如果不是有点麻烦的话。
我试图把这个答案构建成一个很好的通用示例,但我运气不太好。
您可以使用lodash或derby函数lodash
它有两个参数字段数组和方向数组('asc','desc')
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"}
];
var sorted =. data._.orderBy(data, ['city', 'price'], ['asc','desc'])
下面是一种可扩展的按多个字段排序的方法。
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 msort(arr, ...compFns) {
let fn = compFns[0];
arr = [].concat(arr);
let arr1 = [];
while (arr.length > 0) {
let arr2 = arr.splice(0, 1);
for (let i = arr.length; i > 0;) {
if (fn(arr2[0], arr[--i]) === 0) {
arr2 = arr2.concat(arr.splice(i, 1));
}
}
arr1.push(arr2);
}
arr1.sort(function (a, b) {
return fn(a[0], b[0]);
});
compFns = compFns.slice(1);
let res = [];
arr1.map(a1 => {
if (compFns.length > 0) a1 = msort(a1, ...compFns);
a1.map(a2 => res.push(a2));
});
return res;
}
let tstArr = [{ id: 1, sex: 'o' }, { id: 2, sex: 'm' }, { id: 3, sex: 'm' }, { id: 4, sex: 'f' }, { id: 5, sex: 'm' }, { id: 6, sex: 'o' }, { id: 7, sex: 'f' }];
function tstFn1(a, b) {
if (a.sex > b.sex) return 1;
else if (a.sex < b.sex) return -1;
return 0;
}
function tstFn2(a, b) {
if (a.id > b.id) return -1;
else if (a.id < b.id) return 1;
return 0;
}
console.log(JSON.stringify(msort(tstArr, tstFn1, tstFn2)));
//output:
//[{"id":7,"sex":"f"},{"id":4,"sex":"f"},{"id":5,"sex":"m"},{"id":3,"sex":"m"},{"id":2,"sex":"m"},{"id":6,"sex":"o"},{"id":1,"sex":"o"}]
这是一个递归算法,按多个字段排序,同时有机会在比较之前格式化值。
var data = [
{
"id": 1,
"ship": null,
"product": "Orange",
"quantity": 7,
"price": 92.08,
"discount": 0
},
{
"id": 2,
"ship": "2017-06-14T23:00:00.000Z".toDate(),
"product": "Apple",
"quantity": 22,
"price": 184.16,
"discount": 0
},
...
]
var sorts = ["product", "quantity", "ship"]
// comp_val formats values and protects against comparing nulls/undefines
// type() just returns the variable constructor
// String.lower just converts the string to lowercase.
// String.toDate custom fn to convert strings to Date
function comp_val(value){
if (value==null || value==undefined) return null
var cls = type(value)
switch (cls){
case String:
return value.lower()
}
return value
}
function compare(a, b, i){
i = i || 0
var prop = sorts[i]
var va = comp_val(a[prop])
var vb = comp_val(b[prop])
// handle what to do when both or any values are null
if (va == null || vb == null) return true
if ((i < sorts.length-1) && (va == vb)) {
return compare(a, b, i+1)
}
return va > vb
}
var d = data.sort(compare);
console.log(d);
如果a和b相等,它将尝试下一个字段,直到没有可用字段。