关于javascript的排序函数
背景: 根据某些任务的需要,我需要一个简单的排序函数。为了简单起见,我编写了另一个函数,将内置排序函数包装为:关于javascript的排序函数,javascript,sorting,Javascript,Sorting,背景: 根据某些任务的需要,我需要一个简单的排序函数。为了简单起见,我编写了另一个函数,将内置排序函数包装为: function sortBy(obj, extra, func){ if(typeof func == 'function'){ f = func; } else if(typeof extra != 'function'){ eval('function f(a, b, ai, bi, e){return ' + func + '}'
function sortBy(obj, extra, func){
if(typeof func == 'function'){
f = func;
} else if(typeof extra != 'function'){
eval('function f(a, b, ai, bi, e){return ' + func + '}');
} else {
var f = extra;
extra = null;
}
var res = [];
for(var i in obj){
if(obj.hasOwnProperty(i)){
obj[i]._k_ = i;
res.push(obj[i]);
}
}
res.sort(function(a, b){
if(f(a, b, a._k_, b._k_, extra)){
return 1;
} else {
return -1;
}
})
return res;
}
我的尝试是:
var data ={
12: {age:27, name:'pop', role: 'Programmer'},
32: {age:25, name:'james', role: 'Accontant'},
123:{age:19, name:'jerry', role:'Sales Representative'},
15:{age:22, name:'jerry', role:'Coder'},
17:{age:19, name:'jerry', role:'Tester'},
43:{age:14, name:'anna', role: 'Manager'},
55: {age:31, name:'luke', role:'Analyst'}
};
有几种用法:
var b = sortBy(data, '', 'a.age < b.age'); // a simple sort, order by age
var b = sortBy(data, 19, 'b.age == e'); // pick up all records of age 19, and put them in the beginning
var b = sortBy(data, function(a, b){return a.name > b.name}); // anonymous sort function is also allowed
var b=sortBy(数据,,'a.ageb.name});//还允许使用匿名排序函数
问题
虽然它在我们的代码中工作正常,但我想提出一些问题:
我认为传递一个进行比较的函数是合适的
sort(somedata, function(a, b) {
return a < b;
});
排序(一些数据、函数(a、b){
返回a
尝试这样做,以便只对一小部分进行评估:
(小提琴:)
函数排序(obj、extra、func){
var f=null;
if(typeof func=='function'){
f=func;
}else if(额外类型!=“函数”){
f=函数(a、b、ai、bi、e){
返回值(func);//
1.使用eval从字符串创建排序函数是否存在潜在问题
不是本身,但它确实有与调用其他具有字符串的EVE风格函数的相同缺陷,例如“代码> SET TIMEOUT())/>代码>或<代码>函数()/代码>构造函数。只要您相信字符串的源,就没有真正的问题。但是,我将考虑使用<代码>函数< /COD>构造函数代替:
f = new Function(a, b, ai, bi, e, 'return ' + func);
它比评估函数声明更易于管理,而且肯定更合适
2.有没有关于排序函数返回-1(否定)、0和1(肯定)的故事
不太理解问题的这一部分,但如果比较中的两项相同,则函数似乎无法解决该怎么办。根据结果,返回的值应小于0、0或大于0。最好的方法是使用String.prototype.localeCompare()
:
多亏了安迪,我们把代码改为
var f=新函数('a,b,ai,bi,e','return'+func)
请注意,参数应作为字符串传入,请检查:
关于第二个问题,我认为这是因为我们试图使排序函数更明确。
比如说,
排序([1,2,3,5,1],“'a[1,1,2,3,5]
对我们来说,‘a
另一个例子,“a.age
这就是我要问的原因,我们能用真或假来代替-1,0,1吗
我们继续做一些小测试,找出一些东西,希望与大家分享
例如:
var b = [
{age:27, name:'pop 2', role: 'Programmer'},
{age:19, name:'james', role: 'Accontant'},
{age:19, name:'jerry', role:'Sales Representative'},
{age:22, name:'jerry', role:'Coder'},
{age:19, name:'jerry', role:'Tester'},
{age:14, name:'anna', role: 'Manager'},
{age:19, name:'luke', role:'Analyst'},
{age:27, name:'pop', role: 'Programmer'},
{age:14, name:'anna 2', role: 'Manager'}
];
b.sort(function(a, b) {return a.age - b.age > 0? 1: -1}); // #1
b.sort(function(a, b) {return a.age > b.age}); // #2
b.sort(function(a, b) {return a.age - b.age}); // #3
尽管上述排序返回相同的结果,但请尝试以下方法:
b.sort(function(a, b) {return a.age - b.age < 0? -1: 1}); // #4
b.sort(函数(a,b){返回a.age-b.age<0?-1:1});//4
在此语句中,记录仍按年龄排序,但在同一年龄组中顺序相反
#1和#2碰巧与#3相同。如果浏览器使用不同的算法来实现排序功能,
有可能#1和#2的行为类似于#4。如果严格要求结果的顺序,则需要
当“a”等于项“b”时,显式返回0
此外,正如Andy指出的,在某些情况下(例如#4),如果不显式返回0,可能会进行不必要的交换,这可能会影响性能
我们之前没有注意到这一点的原因是,我们不关心提供记录的团队中的订单
是按特定属性排序的。为什么不使用已经存在的排序函数?@dave he是:“我编写了另一个函数,将内置排序函数包装为…”如果我不记得错误的排序函数仅适用于数组对象,对吗?从技术上讲,这比较慢。在原始版本中,eval
在排序之前只运行一次。在您的版本中,每次调用排序函数时,您都会调用编译器。f=new function(…)
在这两种情况下都更合适。谢谢你的第一个答案。这是一个很好的建议我应该在我的答案中指出的一点是性能。如果一个项目不需要移动,应该返回0
,因为这样做的事情更少。例如,一个已经半排序的数组[1,1,1,5,3,4]
。尽管前三项已经就位,但您仍在告诉排序实现移动它们,因此需要做更多的工作。我认为这取决于浏览器如何实现排序功能。例如,在语句#1和#2中,我认为性能与#3(标准的)没有区别,因为已排序的项目保持其原始顺序,是吗?当然在#4中,这需要额外的操作。
var b = [
{age:27, name:'pop 2', role: 'Programmer'},
{age:19, name:'james', role: 'Accontant'},
{age:19, name:'jerry', role:'Sales Representative'},
{age:22, name:'jerry', role:'Coder'},
{age:19, name:'jerry', role:'Tester'},
{age:14, name:'anna', role: 'Manager'},
{age:19, name:'luke', role:'Analyst'},
{age:27, name:'pop', role: 'Programmer'},
{age:14, name:'anna 2', role: 'Manager'}
];
b.sort(function(a, b) {return a.age - b.age > 0? 1: -1}); // #1
b.sort(function(a, b) {return a.age > b.age}); // #2
b.sort(function(a, b) {return a.age - b.age}); // #3
b.sort(function(a, b) {return a.age - b.age < 0? -1: 1}); // #4