Asked  7 Months ago    Answers:  5   Viewed   34 times

I was wondering what was the most efficient way to rotate a JavaScript array.

I came up with this solution, where a positive n rotates the array to the right, and a negative n to the left (-length < n < length) :

Array.prototype.rotateRight = function( n ) {
  this.unshift( this.splice( n, this.length ) );
}

Which can then be used this way:

var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
months.rotate( new Date().getMonth() );

My original version above has a flaw, as pointed out by Christoph in the comments bellow, a correct version is (the additional return allows chaining):

Array.prototype.rotateRight = function( n ) {
  this.unshift.apply( this, this.splice( n, this.length ) );
  return this;
}

Is there a more compact and/or faster solution, possibly in the context of a JavaScript framework? (none of the proposed versions bellow is either more compact or faster)

Is there any JavaScript framework out there with an array rotate built-in? (Still not answered by anyone)

 Answers

44

Type-safe, generic version which mutates the array:

Array.prototype.rotate = (function() {
    // save references to array functions to make lookup faster
    var push = Array.prototype.push,
        splice = Array.prototype.splice;

    return function(count) {
        var len = this.length >>> 0, // convert to uint
            count = count >> 0; // convert to int

        // convert count to value in range [0, len)
        count = ((count % len) + len) % len;

        // use splice.call() instead of this.splice() to make function generic
        push.apply(this, splice.call(this, 0, count));
        return this;
    };
})();

In the comments, Jean raised the issue that the code doesn't support overloading of push() and splice(). I don't think this is really useful (see comments), but a quick solution (somewhat of a hack, though) would be to replace the line

push.apply(this, splice.call(this, 0, count));

with this one:

(this.push || push).apply(this, (this.splice || splice).call(this, 0, count));

Using unshift() instead of push() is nearly twice as fast in Opera 10, whereas the differences in FF were negligible; the code:

Array.prototype.rotate = (function() {
    var unshift = Array.prototype.unshift,
        splice = Array.prototype.splice;

    return function(count) {
        var len = this.length >>> 0,
            count = count >> 0;

        unshift.apply(this, splice.call(this, count % len, len));
        return this;
    };
})();
Tuesday, June 1, 2021
 
DMTintner
answered 7 Months ago
60

Credit goes to this answer for the actual rotation method.

My method was pretty straightforward. Just determine what the row length was, and then iterate through each item, converting the array index to x/y equivalents and then apply the method used in the linked answer to rotate. Finally I converted the rotated X/Y coordinates back to an array index.

var grid = [
  [0,0], [0,1], [0,2], [0,3],
  [1,0], [1,1], [1,2], [1,3],
  [2,0], [2,1], [2,2], [2,3],
  [3,0], [3,1], [3,2], [3,3]
]; 

var newGrid = [];
var rowLength = Math.sqrt(grid.length);
newGrid.length = grid.length

for (var i = 0; i < grid.length; i++)
{
    //convert to x/y
    var x = i % rowLength;
    var y = Math.floor(i / rowLength);

    //find new x/y
    var newX = rowLength - y - 1;
    var newY = x;

    //convert back to index
    var newPosition = newY * rowLength + newX;
    newGrid[newPosition] = grid[i];
}

for (var i = 0; i < newGrid.length; i++)
{   
    console.log(newGrid[i])
}

The output:

[3, 0] [2, 0] [1, 0] [0, 0]  
[3, 1] [2, 1] [1, 1] [0, 1]  
[3, 2] [2, 2] [1, 2] [0, 2]  
[3, 3] [2, 3] [1, 3] [0, 3]  

Fiddle for the lazy. And a 5x5 grid fiddle to demonstrate that the algorithm works for N grid sizes as long as they are square.

Wednesday, June 23, 2021
 
Gil
answered 6 Months ago
Gil
75

You can do the rotation itself using CSS:

.rotated-image {
  -webkit-transform: rotate(20deg);
          transform: rotate(20deg);
}

On the html:

<section id="middle">
    <img id="image" src="images/flower.png" >   
    <button onclick="myFunction()">Click me</button>
</section>

And then, on the javascript, just add the class:

function myFunction() {
  var img = document.getElementById("image");
  img.setAttribute("class", "rotated-image");
}

Check out the result: http://jsbin.com/ibEmUFI/2/edit

Sunday, August 29, 2021
 
Yu Sasaki
answered 3 Months ago
74

There is Array.filter():

var numbers = [1, 2, 3, 4, 5];
var filtered = numbers.filter(function(x) { return x > 3; });

// As a JavaScript 1.8 expression closure
filtered = numbers.filter(function(x) x > 3);

Note that Array.filter() is not standard ECMAScript, and it does not appear in ECMAScript specs older than ES5 (thanks Yi Jiang and jAndy). As such, it may not be supported by other ECMAScript dialects like JScript (on MSIE).

Nov 2020 Update: Array.filter is now supported across all major browsers.

Saturday, September 4, 2021
 
Amumu
answered 3 Months ago
31

Use every() function on the arr and includes() on the str; Every will return true if the passed function is true for all it's items.

var str = 'apple_mango_banana';
var arr = ['apple','banana'];

var isEvery = arr.every(item => str.includes(item));

console.log(isEvery);
Monday, October 18, 2021
 
matthy
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share