如何重写JavaScript数组排序方法?
截至10月31日星期一,这个问题仍然没有得到纠正和回答。人们错误地回答了这个问题,好像我要求修改array.sort,但我不是这样要求的 如何使用基数msd algorthim覆盖单个数组而不是array.sort的内置JavaScript排序方法 我有基数msd排序的算法,它是如何重写JavaScript数组排序方法?,javascript,sorting,overriding,overloading,Javascript,Sorting,Overriding,Overloading,截至10月31日星期一,这个问题仍然没有得到纠正和回答。人们错误地回答了这个问题,好像我要求修改array.sort,但我不是这样要求的 如何使用基数msd algorthim覆盖单个数组而不是array.sort的内置JavaScript排序方法 我有基数msd排序的算法,它是 // radix most-significant-bit sort for integers //arr: array to be sorted //begin: 0 //end: length of array /
// 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
}
}
因此,当我调用homes.sort时,我希望它使用上面的基数排序数组,根据价格对整个homes[x]数组进行排序。我该怎么做?你的问题是问两件事: 如何对数组调用sort,但调用array.sort以外的函数? 如何使排序算法在不硬编码的情况下使用特定字段? 第一个问题的答案是在homes对象本身上附加一个排序方法:
homes.sort = function () {radixSort(homes, 0, homes.length, bit);}
正如一位评论者和其他回答者所指出的那样,这样做会让人非常困惑。首先,Arrays.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);
}
}
但是,请记住以下注意事项:
警告:如果price是浮点值,则基数排序可能不起作用。您最好只使用Array.prototype.sort并传入一个比较器,在不同的字段上进行排序。您的问题有两个: 如何对数组调用sort,但调用array.sort以外的函数? 如何使排序算法在不硬编码的情况下使用特定字段? 第一个问题的答案是在homes对象本身上附加一个排序方法:
homes.sort = function () {radixSort(homes, 0, homes.length, bit);}
正如一位评论者和其他回答者所指出的那样,这样做会让人非常困惑。首先,Arrays.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);
}
}
但是,请记住以下注意事项:
警告:如果price是浮点值,则基数排序可能不起作用。最好只使用Array.prototype.sort并传入一个比较器来对不同字段进行排序。您不需要重写,只需将比较器函数作为参数传递给sort方法即可 参数的函数签名是函数a,b,其中a是与b比较的项 如果需要不同的sort实现,请将其设置为不同的函数,而不是覆盖默认行为。可以使用以下方法对所有阵列执行此操作:
Array.prototype.radixsort = function ( ...params... )
这样你就可以打电话了
[1,2,3].radixsort(...params...);
或者,您可以将实用程序函数添加到阵列:
其名称为:
Array.radixsort([1,2,3], ...params...);
不需要重写,只需将比较器函数作为参数传递给sort方法 参数的函数签名是函数a,b,其中a是与b比较的项 如果需要不同的sort实现,请将其设置为不同的函数,而不是覆盖默认行为。可以使用以下方法对所有阵列执行此操作:
Array.prototype.radixsort = function ( ...params... )
这样你就可以打电话了
[1,2,3].radixsort(...params...);
或者,您可以将实用程序函数添加到阵列:
其名称为:
Array.radixsort([1,2,3], ...params...);
我认为修改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.
}
我认为修改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.
}
继续Ray Toal和ZZBOV的讨论:
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);
}
上述内容可能存在拼写错误,但这应该是迈向更完整实施的一步。继续Ray Toal和Zzbov的讨论:
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);
}
上面可能有输入错误,但这应该是迈向更完整实现的一步。但是如果我做了上面的示例,radixsort如何知道根据数组的Price属性进行排序?我看到你让函数假设了价格属性
ute存在于数组中,但我想将radixsort函数推广为不采用Price属性。实际上OP从未声称要覆盖array.prototype.sort,这显然是危险和愚蠢的,正如你所说的那样他们只是想使用homes.sort语法。通过使用“覆盖”一词,我认为OP清楚地表明了只对homes数组使用排序方法,而不改变所有数组的行为的愿望。@JiminP或任何人,如果你能帮助我概括这一点,这样我就不必将Price硬编码到基数排序函数中,我会让这个答案正确/被接受。请看我上面的评论。但是如果我做了上面的示例,radixsort如何知道根据数组的Price属性进行排序?我看到你让函数假定数组中存在Price属性,但我想将radixsort函数推广为不假定Price属性。实际上OP从未声称要覆盖array.prototype.sort,这显然是危险和愚蠢的,就像你说的那样他们只是想使用homes.sort语法。通过使用“覆盖”一词,我认为OP清楚地表明了只对homes数组使用排序方法,而不改变所有数组的行为的愿望。@JiminP或任何人,如果你能帮助我概括这一点,这样我就不必将Price硬编码到基数排序函数中,我会让这个答案正确/被接受。请参阅我上面的评论。不要用新的行为覆盖默认函数,这将为将来的调试带来巨大的麻烦。@zzzzBov我倾向于同意你的排序,但我不会把这当作一般性的建议,因为默认函数toString是荒谬的,应该被覆盖我知道你的意思。尽管如此,从技术角度来看,这个问题还是有价值的,因此我编辑了答案以解决您的问题。toString和valueOf是作为所有对象的公共接口使用的特殊情况,预期会覆盖这些值。您必须维护通用接口,以使它们正常工作。您不会从toString返回对象或数字,因此如果要覆盖sort,则必须使其与现有接口一起工作,其中第一个参数是比较器函数。哈!这就是为什么在这种情况下即使不是不可能也很难。基数排序是一种分布排序,而不是比较排序,因此非常正确,将排序视为一种通用方法la-toString和toValue没有任何意义,因为基数排序根本不使用比较器。尽管如此,这个问题本身还是很有趣的,因为OP试图创建一个特定于对象的方法,但是,是的,在这个特定的情况下,这样做根本不是正确的。不要用新的行为覆盖默认函数,这将给未来的调试带来巨大的麻烦。@zzzzBov我倾向于同意你的排序,但我不认为这是一般性的建议,因为默认函数toString是荒谬的,应该被重写我知道你的意思。尽管如此,从技术角度来看,这个问题还是有价值的,因此我编辑了答案以解决您的问题。toString和valueOf是作为所有对象的公共接口使用的特殊情况,预期会覆盖这些值。您必须维护通用接口,以使它们正常工作。您不会从toString返回对象或数字,因此如果要覆盖sort,则必须使其与现有接口一起工作,其中第一个参数是比较器函数。哈!这就是为什么在这种情况下即使不是不可能也很难。基数排序是一种分布排序,而不是比较排序,因此非常正确,将排序视为一种通用方法la-toString和toValue没有任何意义,因为基数排序根本不使用比较器。尽管如此,这个问题本身还是很有趣的,因为OP试图创建一个特定于对象的方法,但是是的,在这个特定的案例中,这根本不是正确的做法。我不想重载/重写Array.sort,只想重载Homes.sortN/A-这个答案不适用,因为我不想重写Array.sort。只有homes.sort,除非另有建议。我不想重载/重写Array.sort,只想重载homes.sortN/A-这个答案不适用,因为我不想重写Array.sort。除非有其他明智的建议,否则只能进行排序。