鉴于此代码:
var minX = minY = maxX = maxY = 0;
for(var i=0; i<objArray.length; i++){
if(objArray[i].x < minX){
minX = objArray[i].x;
}else if(objArray [i].x > maxX){
maxX = objArray[i].x;
}
if(objArray[i].y < minY){
minY = objArray[i].y;
}else if(objArray [i].y > maxY){
maxY = objArray[i].y;
}
}
它有效,但我认为它不是很优雅。 它是简单的逻辑,但它使用10行代码。可以改进吗?
答案 0 :(得分:10)
var minX = minY = Number.POSITIVE_INFINITY,
maxX = maxY = Number.NEGATIVE_INFINITY;
for(var i=0; i<objArray.length; i++){
minX = Math.min(objArray[i].x, minX);
minY = Math.min(objArray[i].y, minY);
maxX = Math.max(objArray[i].x, maxX);
maxY = Math.max(objArray[i].y, maxY);
}
对于循环速度优化,您可以将长度存储为仅计算一次:
for(var i=0, len = objArray.length; i<len; i++){
//...
}
检查此article以获取有关循环优化的更多信息。
另一种方法,仅仅是为了“功能性乐趣”,因为我不推荐它的性能,可能是使用Array.map将x和y值分成两个数组,并且然后使用apply调用最小和最大函数:
var allX = objArray.map(function (o) { return o.x; });
var allY = objArray.map(function (o) { return o.y; });
minX = Math.min.apply(Math, allX);
minY = Math.min.apply(Math, allY);
maxX = Math.max.apply(Math, allX);
maxY = Math.max.apply(Math, allY);
这是如何运作的?
apply函数用于调用具有给定上下文和参数的另一个函数,作为数组提供。 min和max函数可以使用任意数量的输入参数:Math.max(val1,val2,...,valN)
所以如果我们打电话:
Math.min.apply(Math, [1,2,3,4]);
apply函数将执行:
Math.min(1,2,3,4);
请注意,第一个参数(上下文)对于这些函数并不重要,因为它们是静态的,无论作为上下文传递什么,它们都将起作用。
答案 1 :(得分:5)
它最多使用10行代码。
但是,LoC不是优化的衡量标准。
我在Firefox 3.5中测试了上述算法。 (有关测试用例,请参见下文。)
您的原始代码(methodA)几乎是CMS(methodB)的两倍! Math.min的使用使他的版本更具可读性,并且在大多数情况下这是重要的。但它确实引入了更多的查找和函数调用,这会减慢它的速度。
'功能性乐趣'版本(methodC)实际上比任何一个版本快得多!这对我来说是一个惊喜,因为这个版本必须构建两个临时数组,但似乎很好地使用apply()来一次性完成所有比较,弥补了这一点。但是,这是在Firefox上,其中有一个Array.map()的本机实现。没有此功能的IE浏览器需要将JavaScript版本入侵到Array原型中,这使得methodC对于我来说就像方法B一样慢。
正如预期的那样,史蒂思的替代功能版本非常缓慢;所有这些临时物品都会造成损失。最后我管理的最快的是采用原始方法A并调整它以删除每循环.length访问,并微观优化多个属性访问。令人惊讶的是,这个(方法E)敲了一下。
但是,所有这些通常都是特定于浏览器的。我只在一个浏览器上测试过;你可能会对别人有不同的结果。通常微优化不会得到回报,你最好选择最易读的选项。
<script type="text/javascript">
var objArray= [];
for (var i= 0; i<1000000; i++) {
objArray.push({'x': Math.floor(Math.random()*100000), 'y': Math.floor(Math.random()*100000)});
}
function methodA() {
var t= new Date();
var minX = minY = maxX = maxY = 0;
for(var i=0; i<objArray.length; i++){
if(objArray[i].x < minX){
minX = objArray[i].x;
}else if(objArray [i].x > maxX){
maxX = objArray[i].x;
}
if(objArray[i].y < minY){
minY = objArray[i].y;
}else if(objArray [i].y > maxY){
maxY = objArray[i].y;
}
}
alert(new Date()-t);
}
function methodB() {
var t= new Date();
var minX = minY = Number.POSITIVE_INFINITY,
maxX = maxY = Number.NEGATIVE_INFINITY;
for(var i=0; i<objArray.length; i++){
minX = Math.min(objArray[i].x, minX);
minY = Math.min(objArray[i].y, minY);
maxX = Math.max(objArray[i].x, maxX);
maxY = Math.max(objArray[i].y, maxY);
}
alert(new Date()-t);
}
function methodC() {
var t= new Date();
var allX = objArray.map(function (o) { return o.x; });
var allY = objArray.map(function (o) { return o.y; });
minX = Math.min.apply(Math, allX);
minY = Math.min.apply(Math, allY);
maxX = Math.max.apply(Math, allX);
maxY = Math.max.apply(Math, allY);
alert(new Date()-t);
}
function methodD() {
var t= new Date();
var minX = objArray.reduce( function(a,b) { return {x : Math.min(a.x,b.x)};}).x;
var minY = objArray.reduce( function(a,b) { return {y : Math.min(a.y,b.y)};}).y;
var maxX = objArray.reduce( function(a,b) { return {x : Math.max(a.x,b.x)};}).x;
var maxY = objArray.reduce( function(a,b) { return {y : Math.max(a.y,b.y)};}).y;
alert(new Date()-t);
}
function methodE() {
var t= new Date();
var minX = minY = maxX = maxY = 0;
var o, v;
for (var i=objArray.length; i-->0;) {
o= objArray[i];
v= o.x;
if (v<minX) minX= v;
if (v>maxX) maxX= v;
v= o.y;
if (v<minY) minY= v;
if (v>maxY) maxY= v;
}
alert(new Date()-t);
}
</script>
<button onclick="methodA()">A</button>
<button onclick="methodB()">B</button>
<button onclick="methodC()">C</button>
<button onclick="methodD()">D</button>
<button onclick="methodE()">E</button>
答案 2 :(得分:1)
到目前为止,所有答案似乎都是在比较中使用未初始化的变量(minX等)。这是一个功能强大,优雅的解决方案:
var minX = anarray.reduce( function(a,b) { return {x : Math.min(a.x,b.x)};}).x;
var minY = anarray.reduce( function(a,b) { return {y : Math.min(a.y,b.y)};}).y;
var maxX = anarray.reduce( function(a,b) { return {x : Math.max(a.x,b.x)};}).x;
var maxY = anarray.reduce( function(a,b) { return {y : Math.max(a.y,b.y)};}).y;
查看here以获取有关reduce函数的说明以及如何在本机不支持它的浏览器中启用它。