Массив JavaScript вращается ()

Я задавался вопросом, что самый эффективный путь состоял в том, чтобы повернуть массив JavaScript.

Я предложил это решение, где положительное n поворачивает массив направо и отрицание n налево (-length < n < length) :

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

Который может затем использоваться этот путь:

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

Моя исходная версия выше имеет дефект, как указано Christoph в реве комментариев, правильная версия (дополнительный возврат позволяет объединять в цепочку):

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

Существует ли более компактное и/или более быстрое решение, возможно в контексте платформы JavaScript? (ни один из предложенного рева версий не или более компактен или быстрее),

Есть ли какая-либо платформа JavaScript там с массивом, вращаются встроенный? (Все еще отвеченный любым)

64
задан Victor 10 April 2018 в 14:26
поделиться

4 ответа

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;
    };
})();

В комментариях Жан поднял вопрос о том, что код не поддерживает перегрузку push() и splice(). Я не думаю, что это действительно полезно (см. комментарии), но быстрым решением (хотя и немного хакерским) было бы замена строки

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

на эту:

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

Использование unshift() вместо push() в Опера 10 почти в два раза быстрее, в то время как различия в FF были незначительны; код:

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;
    };
})();
49
ответ дан 24 November 2019 в 15:36
поделиться

Если ваш массив будет большим и/или вы будете много вращаться, вы можете рассмотреть возможность использования связанного списка вместо массива.

.
0
ответ дан 24 November 2019 в 15:36
поделиться

Как насчет инкремента счетчика, а затем получения остатка деления на длину массива, чтобы попасть туда, где вы должны быть.

var i = 0;
while (true);
{
    var position = i % months.length;
    alert(months[position]);
    ++i;
}

Синтаксис языка в стороне от этого должен работать нормально.

0
ответ дан 24 November 2019 в 15:36
поделиться

Наверное, я бы сделал что-нибудь вроде этого:

Array.prototype.rotate = function(n) {
    return this.slice(n, this.length).concat(this.slice(0, n));
}

Edit Here's a mutator version:

Array.prototype.rotate = function(n) {
    while (this.length && n < 0) n += this.length;
    this.push.apply(this, this.splice(0, n));
    return this;
}
32
ответ дан 24 November 2019 в 15:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: