Rounding to the nearest Nth value in array [bestpractice]

2 views
Skip to first unread message

jiggliemon

unread,
Jun 21, 2010, 2:00:22 AM6/21/10
to MooTools Users
I've saved some uploaded images to various sizes, and would like to
retrieve the smallest image possible, based on the browsers window
size.

I created a "Rounder" class that you feed an array of integers into,
and based on the number you feed an up, or down method, it will return
the next nearest value. It just feels that im going about it in a
mostly inefficient way. What do you think?

jsfiddle:
------------
http://jsfiddle.net/G3j9D/1/

Class:
------------
var Rounder = new Class({
Implements: Options,
options:{
steps: []
},
initialize: function(steps,options){
this.setOptions(options);
this.steps = steps;
},
up: function(integer){
var allOver = this.steps.filter(function(item){
return item > integer;
});

return (allOver.length)?
allOver[0]:Math.max.apply(Math,this.steps);
},
down: function(integer){
var allUnder = this.steps.filter(function(item){
return item < integer;
});
return allUnder[0];
}
});

nwhite

unread,
Jun 21, 2010, 3:11:25 AM6/21/10
to mootool...@googlegroups.com
It depends on why you want to optimize. Currently, the code works fine unless you pass a number out of range and try to round down. In your example I expect rounding 400 down would return 240 and not 0, and -10 return 0 instead of undefined.

For me the Array.filter callbacks are the most inefficient part of the code. We have to touch every item in the array with a function callback.



var Rounder new Class({
    
    initializefunction(steps,options){
        this.steps steps.sort(function(a,b){
            return parseInt(aparseInt(b);
        });
    },

    upfunction(num){
        for(var i=0,l=this.steps.lengthi<li++)
            if(this.steps[inumreturn this.steps[i];
        return this.steps[this.steps.length-1];
    },

    downfunction(num){
        for(var i=this.steps.length-1i>=0i--)
            if(this.steps[inumreturn this.steps[i];
        return this.steps[0];
    }
});

I sorted 'this.steps' in 'initialize' to help make the code for 'up' and 'down' do less work. This way if I'm rounding up I can exit as soon as I find a value that is higher else I return the highest number in this.steps. When rounding down I start from the back of the array since my larger numbers are there. As soon as a number is lower the code returns if no value is lower it returns the lowest in this.steps. Doing this removes the 'out of range' bug with 'down'. It also make the rounding algorithm worst case O(n), whereas your example is always O(n).

jiggliemon

unread,
Jun 21, 2010, 1:59:43 PM6/21/10
to MooTools Users
My issues was with the Array.filter as well. I was hoping there would
be a way to avoid looping through the stack all together.
It appears that it's impossible.
I made a few minor adjustments. cause when 30 was entered... it still
rounded to 15, and 60.
Also moved the sort to it's own method. Possibly get some singletons
going.

Thanks for your help.

http://jsfiddle.net/NtbBn/2/
Reply all
Reply to author
Forward
0 new messages