从这个最初的问题,我将如何在多个字段应用排序?
使用这种稍作调整的结构,我将如何排序城市(上升)和价格(下降)?
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 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"}
];
function sortBy(ar) {
return ar.sort((a, b) => a.city === b.city ?
b.price.toString().localeCompare(a.price) :
a.city.toString().localeCompare(b.city));
}
console.log(sortBy(homes));
另一种方式
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"}
];
function sortBy(ar) {
return ar.sort((a, b) => a.city === b.city ?
b.price.toString().localeCompare(a.price) :
a.city.toString().localeCompare(b.city));
}
console.log(sortBy(homes));
一个动态的方法来做到这与多个键:
从排序的每个col/key中过滤唯一的值
按顺序排列或颠倒
根据indexOf(value)键值为每个对象添加weights width zeropad
使用计算的权重进行排序
Object.defineProperty(Array.prototype, 'orderBy', {
value: function(sorts) {
sorts.map(sort => {
sort.uniques = Array.from(
new Set(this.map(obj => obj[sort.key]))
);
sort.uniques = sort.uniques.sort((a, b) => {
if (typeof a == 'string') {
return sort.inverse ? b.localeCompare(a) : a.localeCompare(b);
}
else if (typeof a == 'number') {
return sort.inverse ? b - a : a - b;
}
else if (typeof a == 'boolean') {
let x = sort.inverse ? (a === b) ? 0 : a? -1 : 1 : (a === b) ? 0 : a? 1 : -1;
return x;
}
return 0;
});
});
const weightOfObject = (obj) => {
let weight = "";
sorts.map(sort => {
let zeropad = `${sort.uniques.length}`.length;
weight += sort.uniques.indexOf(obj[sort.key]).toString().padStart(zeropad, '0');
});
//obj.weight = weight; // if you need to see weights
return weight;
}
this.sort((a, b) => {
return weightOfObject(a).localeCompare( weightOfObject(b) );
});
return this;
}
});
Use:
// works with string, number and boolean
let sortered = your_array.orderBy([
{key: "type", inverse: false},
{key: "title", inverse: false},
{key: "spot", inverse: false},
{key: "internal", inverse: true}
]);
下面是一种可扩展的按多个字段排序的方法。
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 sort(data, orderBy) {
orderBy = Array.isArray(orderBy) ? orderBy : [orderBy];
return data.sort((a, b) => {
for (let i = 0, size = orderBy.length; i < size; i++) {
const key = Object.keys(orderBy[i])[0],
o = orderBy[i][key],
valueA = a[key],
valueB = b[key];
if (!(valueA || valueB)) {
console.error("the objects from the data passed does not have the key '" + key + "' passed on sort!");
return [];
}
if (+valueA === +valueA) {
return o.toLowerCase() === 'desc' ? valueB - valueA : valueA - valueB;
} else {
if (valueA.localeCompare(valueB) > 0) {
return o.toLowerCase() === 'desc' ? -1 : 1;
} else if (valueA.localeCompare(valueB) < 0) {
return o.toLowerCase() === 'desc' ? 1 : -1;
}
}
}
});
}
使用:
sort(homes, [{city : 'asc'}, {price: '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"}
];
function sort(data, orderBy) {
orderBy = Array.isArray(orderBy) ? orderBy : [orderBy];
return data.sort((a, b) => {
for (let i = 0, size = orderBy.length; i < size; i++) {
const key = Object.keys(orderBy[i])[0],
o = orderBy[i][key],
valueA = a[key],
valueB = b[key];
if (!(valueA || valueB)) {
console.error("the objects from the data passed does not have the key '" + key + "' passed on sort!");
return [];
}
if (+valueA === +valueA) {
return o.toLowerCase() === 'desc' ? valueB - valueA : valueA - valueB;
} else {
if (valueA.localeCompare(valueB) > 0) {
return o.toLowerCase() === 'desc' ? -1 : 1;
} else if (valueA.localeCompare(valueB) < 0) {
return o.toLowerCase() === 'desc' ? 1 : -1;
}
}
}
});
}
console.log(sort(homes, [{city : 'asc'}, {price: 'desc'}]));