如何覆盖JavaScript数组排序方法?

时间:2011-10-31 04:33:05

标签: javascript sorting override overloading

此问题仍未在10月31日星期一之前得到纠正 (人们错误地回答它,好像我要求修改array.sort但我不是问那个)

如何使用radix-msd algorthim覆盖单个数组(不是Array.sort)的内置JavaScript排序方法?

我有基数msd排序的算法,它是

// radix most-significant-bit sort for integers
//arr: array to be sorted
//begin: 0
//end: length of array
//bit: maximum number of bits required to represent numbers in arr
function radixsort (arr, begin, end, bit) {
    var i, j, mask;
    i = begin;
    j = end;
    mask = 1 << bit;
    while(i < j) {
        while(i < j && !(arr[i] & mask)) {
            ++i;
        }
        while(i < j && (arr[j - 1] & mask)) {
            --j;
        }
        if(i < j) {
            j--;
            var tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
            i++;
        }
    }
    if(bit && i > begin) {
        radixsort(arr, begin, i, bit - 1);   //    <=== RECURSIVE FUNCTION
    }
    if(bit && i < end) {
        radixsort(arr, i, end, bit - 1);     //    <=== RECURSIVE FUNCTION
    }
}

我的JavaScript对象数组是:

homes[0].price;
homes[0].address;
homes[0].city;
homes[0].state;
homes[0].zip;

因此,当我调用“homes.sort()”时 - 我希望它使用上面的homes[x]数组基于price对整个radix sort数组进行排序。 我该怎么做?

4 个答案:

答案 0 :(得分:5)

您无需覆盖sort function,只需将比较器函数作为参数传递给sort方法。

参数的函数签名为function (a, b),其中a是与b进行比较的项目。

如果需要不同的sort实现,请将其设置为不同的函数,而不是覆盖默认行为。您可以使用以下命令对所有阵列执行此操作:

Array.prototype.radixsort = function ( ...params... )

这将允许您致电

[1,2,3].radixsort(...params...);

或者,您可以向Array添加实用程序功能:

Array.radixsort = function ( ...params... )

将被称为:

Array.radixsort([1,2,3], ...params...);

答案 1 :(得分:1)

我认为修改Array.prototype.sort 非常很危险(因为可能使用sort()的所有其他代码都会受到影响)。这是代码:

//Just use this function like radixsort(homes,0,homes.length,32)
function radixsort (arr, begin, end, bit) {
    var i, j, mask;
    i = begin;
    j = end;
    mask = 1 << bit;
    while(i < j) {
        while(i < j && !(arr[i].price & mask)) {
            ++i;
        }
        while(i < j && (arr[j - 1].price & mask)) {
            --j;
        }
        if(i < j) {
            j--;
            var tmp = arr[i].price;
            arr[i].price = arr[j].price;
            arr[j].price = tmp;
            i++;
        }
    }
    if(bit && i > begin) {
        radixsort(arr, begin, i, bit - 1);
    }
    if(bit && i < end) {
        radixsort(arr, i, end, bit - 1);
    }
}
//If you really want to modify default sort function:
Array.prototype.sort = function(){
    radixsort(this,0,this.length,32); //Use 'this' to access (get reference) to the array.
}

答案 2 :(得分:0)

扩展Ray Toal和zzzzBov的讨论:

  function defaultCompare(a, b) {
      var a_str = str(a);
      var b_str = str(b);
      if (a_str < b_str) {
          return -1;
      } else if (a_str > b_str) {
          return 1;
      } else {
          return 0;
      }
   }

   homes.sort = function (compare_func) {
       compare_func = compare_func || defaultCompare;
       RadixSort(this, 0, this.length, 64);
   }

上面可能存在拼写错误,但这应该是迈向更完整实施的一步。

答案 3 :(得分:-2)

你的问题是要问两件事:

  1. 如何在数组上调用sort但是调用Array.sort以外的函数?
  2. 如何在不对其进行硬编码的情况下使排序算法使用特定字段?
  3. 第一个问题的答案是在sort对象本身附加homes方法:

    homes.sort = function () {radixSort(homes, 0, homes.length, bit);}
    

    作为其中一位评论者和其他回答者指出,这样做可能会非常混乱。首先,Arrays.sort采用第二个参数,它是一个比较函数。基数排序是基于分布的排序,而不是基于比较的排序,因此以这种方式“覆盖”sort没有多大意义。如果有人传递它,你会忽略比较函数。

    但还有另一个问题。您写的radixSort不起作用,因为它不会比较价格。其中一个答案硬编码价格,但你说你不喜欢这种情况。您可以按如下方式解决此问题:添加第五个参数,即字段名称。如果未定义,请使用数组元素本身,否则请选择该字段。这样的事情(未经测试):

    function radixsort (arr, begin, end, bit, field) {
        var i = begin, j = end , mask = 1 << bit;
        // Use the value of the field at i if present, otherwise the whole element
        var at = function (i) {return field in arr ? arr[i][field] : arr[i]};
        while (i < j) {
            while (i < j && !(arr.at(i) & mask)) {
                ++i;
            }
            while (i < j && (arr.at(j-1) & mask)) {
                --j;
            }
            if (i < j) {
                j--;
                var tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
                i++;
            }
        }
        if (bit && i > begin) {
            radixsort(arr, begin, i, bit - 1);
        }
        if (bit && i < end) {
            radixsort(arr, i, end, bit - 1);
        }
    }
    

    现在你可以说:

    homes.sort = function () {radixSort(homes, 0, homes.length, 64, 'price');}
    

    但是,请记住以下警告:

    CAVEAT :如果price是浮点值,则基数排序可能不起作用。最好的办法是只使用Array.prototype.sort并传入比较器对不同的字段进行排序。