Forums > Javascript

Issue rotating an array

April 11, 2013 | 2:11 am

Hi there, I’m trying to emulate the [zl rot] object in javascript for use in a bigger js project.

I’m almost there but I’m having a bit of trouble.

The bellow code works for positive values:

—————————–
autowatch = 1;

inlets = 1;
outlets = 1;

function rotate(rota)
{
rotaArr = [0, 1, 2, 3, 4, 5, 6, 7, 8];

if(rota > 0)
{
for(i = 0; i < rota; i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}
post("rotaArr " + rotaArr);
post();
}
—————————–

yet if I want to reference an array declared in as global variable the global variable changes as well as the rotation array.
Like this:
—————————–
autowatch = 1;

inlets = 1;
outlets = 1;

var theArray = [0, 1, 2, 3, 4, 5, 6, 7, 8];

function rotate(rota)
{
rotaArr = theArray;

if(rota > 0)
{
for(i = 0; i < rota; i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}
post("TheArray " + theArray + " rotaArr " + rotaArr);
post();
}
—————————–

I really can’t see why there is any difference in functionality.
How can ‘theArray’ change to the same as ‘rotaArr’ without me calling any modifiers on it?

Any guidance would be much appreciated.


April 11, 2013 | 9:03 am

Hi,

I’m not sure what’s happening here but I have I few ideas:

i) in your function rotate, you’re declaring the variable rotaArr without the ‘var’ keyword. I think this will make it act like a global instead of being local to the function – which could cause problems.

ii) there’s no ‘return’ at the end of the function

iii) It might be useful to pass the array you’re working on as an argument to the function.

This gives something like:

function rotate(rotaArr, rota)
{

if(rota > 0) {
for(i = 0; i < rota; i++){
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}
return rotaArr;
}

So, to modify the global array you could call it like this:

theArray = rotate(theArray, 2);

I’m away from max, so can’t prove any of this but maybe some of it will help.

best

Richard


April 11, 2013 | 2:10 pm

Hi, thanks for chipping in.
I’ve tried your suggestions.
Declaring
var rotaArr = theArray;
seems to give no different results from simply
rotaArr = theArray;

adding
return rotaArr;
before the post statement stops the post statement from being called for some reason
afterwards and the functionality is the same.

I’m calling this function from max with the message ‘rotate int’. adding the extra argument inside js seems to confuse the function.
I get the error message ‘error calling function rotate…….rotaArr is undefined’

I assume this is because I am not passing the Array from Max along with the message ‘rotate int’.

Any more ideas? I’ve searched the forums and google for an answer but nothings fixed it yet.


April 11, 2013 | 2:41 pm

Hello,

Try using two inputs and write a list() function to input your array and a msg_int function to take the int by which you want to rotate. Take a look at the max javascript help stuff.

If no-one else chimes in, I’ll try to be more specific but I have to rush out just now.

best

richard


April 11, 2013 | 3:09 pm

shift() and push() both side-effect the array. Try cloning it first: http://davidwalsh.name/javascript-clone-array


April 11, 2013 | 3:42 pm

aha! cloning the array works!

I just want to confirm one thing though. In js(Max flavour) is it entirely necessary to ‘return’ at the end of every function?
Even if the function is just to update a global variable or to call another function?
Where exactly does the returned value go?
Sorry for my naivety but I’m just getting into using js in my everyday Max programming and there are a few things I need to get solid in my mind.

Here is the full code for both positive and negative rotations for anyone who’s interested:

function rotate(rota)
{
var rotaArr = theArray.slice(0);

if(rota > 0)
{
for(i = 0; i < rota; i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}
if(rota < 0)
{
for(i = 0; i < theArray.length+rota; i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}

post("TheArray " + theArray + " rotaArr " + rotaArr);
post();
return rotaArr;

}


April 11, 2013 | 4:01 pm

And here is a version that works with any positive and negative values using the Euclidean Modulo technique I found somewhere on this forum.

autowatch = 1;

inlets = 1;
outlets = 1;

var theArray = [0, 1, 2, 3, 4, 5, 6, 7, 8];
var rotaArr = theArray;
var oldVariable

function rotate(rota)
{
var rotaArr = theArray.slice(0);//clone the Array
rota = rota%theArray.length; //modulo rota

if(rota > 0) //if positive value
{
for(i = 0; i < (rota); i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}
if(rota < 0) //if negative value
{
if(theArray.length>0)
{
divisor = theArray.length * 1;
}
else
{
divisor = theArray.length * -1;
}
rota = rota + divisor;
for(i = 0; i < rota; i++)
{
offCut = rotaArr.shift();
rotaArr.push(offCut);
}
}

post("TheArray " + theArray + " rotaArr " + rotaArr);
post();
return rotaArr;

}


Viewing 7 posts - 1 through 7 (of 7 total)