我知道这个网站周围有很多这样的问题,但是我很挣扎,在尝试之前我曾尝试做过我的作业。
我有一个对象数组,每个对象都有三个字段。状态,类型和时间。都是整数。
状态介于1-9之间,表示可用性和所有内容 按状态排序。
类型表示用户是否为0 - “付费”或1 - “免费”。付出了 永远高于自由。
这是我的代码
function sortListings(obj1, obj2) {
var statusA = obj1.status;
var statusB = obj2.status;
var typeA = obj1.type;
var typeB = obj2.type;
if (typeA == typeB) {
return (statusA < statusB) ? -1 : (statusA > statusB) ? 1 : 0;
} else {
return (typeA < typeB ) ? -1 : 1;
}
}
这很有效。现在有时两个对象将具有相同的状态并且处于相同的付费类型。所以我想在这种情况下首先提供最新的时间戳。
我不知道怎么回事。这是我的尝试:
function sortListing(obj1, obj2) {
var statusA = obj1.status;
var statusB = obj2.status;
var typeA = obj1.type;
var typeB = obj2.type;
var timeA = obj1.time;
var timeB = obj2.time;
if (typeA == typeB) { // has the same type
if (statusA == statusB) { // has the same status
return timeA - timeB; //so sort by time
} else { // different statues, same type
return (statusA < statusB) ? -1 : (statusA > statusB) ? 1 : 0; // sort by status
}
} else {
return (typeA < typeB ) ? -1 : 1;
}
}
正如你所看到的,我对排序内部运作的了解并不是那么好。 非常感谢任何文章,答案或评论。
答案 0 :(得分:5)
如果较高级别的字段相同,则您的主要问题是不太重要的字段。试试这个:
function sortListing(obj1, obj2) {
function compareType(a, b) {
return a.type - b.type;
}
function compareStatus(a, b) {
return a.status - b.status;
}
function compareTime(a, b) {
return a.time - b.time;
}
return compareType(obj1, obj2) ||
compareStatus(obj1, obj2) ||
-compareTime(obj1, obj2); // negative to reverse order
}
||
短路运算符将导致仅在先前比较返回0时评估第二个(以及随后的第三个)比较。仅通过更改三个函数的顺序来简单地更改排序顺序调用。
当然,内部函数可以在更高级别的范围内公开,允许您单独使用每个比较器函数,或者以交替顺序使用。
另请注意,除非绝对必要,否则此方法如何避免取消引用任何对象属性。如果你正在排序数千个可以产生显着差异的条目,尽管在实践中可能会被内部进行三个函数调用的潜在费用所抵消....只有基准才能真正说明。
答案 1 :(得分:2)
我会以不同的方式构造代码。首先比较最重要的键,然后是下一个最重要的键,依此类推。只有当你比较了所有的密钥并发现它们都相同时,才会返回0
。
function sortListing(obj1, obj2) {
var statusA = obj1.status;
var statusB = obj2.status;
var typeA = obj1.type;
var typeB = obj2.type;
var timeA = obj1.time;
var timeB = obj2.time;
if (typeA < typeB)
return -1;
if (typeA > typeB)
return 1;
if (statusA < statusB)
return -1;
if (statusA > statusB)
return 1;
if (timeA < timeB)
return -1;
if (timeA > timeB)
return 1;
return 0;
}
现在,只要你看到一段看起来像是一遍又一遍重复的同样的代码,你的头脑中应该会发出一些信息:
function compareKeys(k1, k2) {
for (var i = 0; i < k1.length; ++i) {
if (k1[i] < k2[i]) return -1;
if (k1[i] > k2[i]) return 1;
}
return 0;
}
function sortListing(obj1, obj2) {
return compareKeys([obj1.type, obj1.status, obj1.time], [obj2.type, obj2.status, obj2.time]);
}
另一个改进:
function pluck(obj, keynames) {
var keys = [];
for (var i = 0; i < keynames.length; ++i) // could be done with .map()
keys.push(obj[keynames[i]]);
return keys;
}
function sortListing(obj1, obj2) {
var keynames = ["type", "status", "time"];
return compareKeys(pluck(obj1, keynames), pluck(obj2, keynames));
}
答案 2 :(得分:1)
我无法抗拒尝试一种强调这个问题的递归性质的解决方案。你基本上比较了两个这样的数组:你比较第一个元素,如果第一个元素相同,那么你用相同的方式比较其余的元素。
这是比较数组的函数(假设数组长度相同):
function compareArray(a1,a2) {
if (a1[0]==a2[0]) {
if (a1.length==1) {
return 0;
}
else {
return compareArray(a1.slice(1),a2.slice(1));
}
}
else {
return (a1[0]<a2[0] ) ? -1 : 1;
}
}
与try / catch相同的函数来检查长度:
function compareArray(a1, a2) {
var l = a1.length;
try {
if (l != a2.length) throw "arrays have diff. size";
if (l == 0) throw "empty array";
var h1 = a1[0];
var h2 = a2[0];
if (h1 == h2) {
if (l == 1) {
return 0;
} else {
return compareArray(a1.slice(1), a2.slice(1));
}
} else {
return (h1 < h2) ? -1 : 1;
}
} catch (err) {
// handle err
}
}
然后你可以比较字段
function sortListings(obj1, obj2) {
var statusA = obj1.status;
var statusB = obj2.status;
var typeA = obj1.type;
var typeB = obj2.type;
var timeA = obj1.time;
var timeB = obj2.time;
return compareArray([statusA,typeA,timeA],[statusB,typeB,timeB])
}
顺便说一句,您可以使用compareArray
来比较任意数量的字段。