Javascript和更高级的排序

时间:2014-06-30 20:52:51

标签: javascript arrays sorting

我知道这个网站周围有很多这样的问题,但是我很挣扎,在尝试之前我曾尝试做过我的作业。

我有一个对象数组,每个对象都有三个字段。状态,类型和时间。都是整数。

  • 状态介于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;
        }
    }

这很有效。现在有时两个对象将具有相同的状态并且处于相同的付费类型。所以我想在这种情况下首先提供最新的时间戳。

  • 时间存储为int(unix)

我不知道怎么回事。这是我的尝试:

  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;
        }
    }

正如你所看到的,我对排序内部运作的了解并不是那么好。 非常感谢任何文章,答案或评论。

3 个答案:

答案 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来比较任意数量的字段。