Javascript 如何调整数组大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32054170/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:34:09  来源:igfitidea点击:

How to resize an array

javascriptarrays

提问by hansmaad

Is there an Array method that can replace the following function (Something like a.splice(some, tricky, arguments))?

是否有可以替换以下函数的 Array 方法(类似a.splice(some, tricky, arguments))?

function resize(arr, newSize, defaultValue) {
  if (newSize > arr.length)
    while(newSize > arr.length)
      arr.push(defaultValue);
  else
    arr.length = newSize;
}

If not, is there a better / nicer / shorter / implementation? The function should append a default value if the array should grow and remove values on shrink.

如果没有,是否有更好/更好/更短/实现?如果数组应该增长并在收缩时删除值,则该函数应该附加一个默认值。

采纳答案by James Brierley

In terms of elegance, I would say you could trim down your original solution to:

就优雅而言,我会说您可以将原始解决方案缩减为:

function resize(arr, newSize, defaultValue) {
    while(newSize > arr.length)
        arr.push(defaultValue);
    arr.length = newSize;
}

Or use prototype:

或者使用原型:

Array.prototype.resize = function(newSize, defaultValue) {
    while(newSize > this.length)
        this.push(defaultValue);
    this.length = newSize;
}

Edit: ES2016 approach:

编辑:ES2016 方法:

function resize(arr, newSize, defaultValue) {
    return [ ...arr, ...Array(Math.max(newSize - arr.length, 0)).fill(defaultValue)];
}

回答by wayofthefuture

function resize(arr, size, defval) {
    while (arr.length > size) { arr.pop(); }
    while (arr.length < size) { arr.push(defval); }
}

I think this would be more efficient though:

我认为这会更有效:

function resize(arr, size, defval) {
    var delta = arr.length - size;

    while (delta-- > 0) { arr.pop(); }
    while (delta++ < 0) { arr.push(defval); }
}

And while not as elegant, this would probably me the most efficient:

虽然不那么优雅,但这可能是我最有效的:

function resize(arr, size, defval) {
    var delta = arr.length - size;

    if (delta > 0) {
        arr.length = size;
    }
    else {
        while (delta++ < 0) { arr.push(defval); }
    }
}

回答by Ori Drori

This solution will only work for new browsers (except IE) due to Array.prototype.fill(see Browser compatibility at the bottom of the linked page) or using a polyfill.

由于Array.prototype.fill(请参阅链接页面底部的浏览器兼容性)或使用 polyfill,此解决方案仅适用于新浏览器(IE 除外)。

function resize(arr, newSize, defaultValue) {
    var originLength = arr.length; // cache original length

    arr.length = newSize; // resize array to newSize

    (newSize > originLength) && arr.fill(defaultValue, originLength); // Use Array.prototype.fill to insert defaultValue from originLength to the new length
}

回答by crush

Expanding on James solution:

扩展 James 解决方案:

Array.prototype.resize = function(newSize, defaultValue) {
    while(newSize > this.length)
        this.push(defaultValue);
    this.length = newSize;
}

If you want to get even more efficient, you could do browser detection for Array.prototype.filland use that instead of the while loop.

如果您想获得更高的效率,您可以进行浏览器检测Array.prototype.fill并使用它而不是 while 循环。

if (Array.prototype.fill) {
    Array.prototype.resize = function (size, defaultValue) {
        var len = this.length;

        this.length = size;

        if (this.length - len > 0)
            this.fill(defaultValue, len);
    };
} else {
    Array.prototype.resize = function (size, defaultValue) {
        while (size > this.length)
            this.push(defaultValue);

        this.length = size;
    };
}

If someone has included a polyfill for Array.prototype.fill, then you want them to use your non-fill version instead. A polyfill would cause the fill method to be slower than the non-fill version.

如果有人为 包含了 polyfill Array.prototype.fill,那么您希望他们改用您的非填充版本。polyfill 会导致填充方法比非填充版本慢。

This StackOverflow Q&Adeals with how to detect if a function is natively implemented. You could work that into the initial condition, but that is just additional speed lost.

这个StackOverflow 问答处理如何检测一个函数是否是原生实现的。您可以将其应用于初始条件,但这只是额外的速度损失。

I'd probably only use this solution if you could ensure that no Array.prototype.fillwould exist.

如果您可以确保不Array.prototype.fill存在,我可能只会使用此解决方案。

回答by Reza

You can use the following code for resizing arrays:

您可以使用以下代码调整数组大小:

// resizing function for arrays
Array.prototype.resize = function( newSize, defaultValue )
{
  while( newSize > this.length )
  {
    typeof( defaultValue ) === "object" ? this.push( Object.create( defaultValue ) ) : this.push( defaultValue );
  }
  this.length = newSize;
}

I checked the type of defaultValuebecause if it is an object and you just push it to the new elements, you will end up with an array which new elements point to the same object. That means if you change a property of that object in one of your array's element, all others will also change. But if your defaultValueis a primitive, you can safely push it to the new elements.

我检查了 的类型,defaultValue因为如果它是一个对象并且你只是将它推送到新元素,你最终会得到一个数组,其中新元素指向同一个对象。这意味着如果您在数组元素之一中更改该对象的属性,则所有其他元素也将更改。但是如果你defaultValue是一个原语,你可以安全地将它推送到新元素。

回答by Константин Ван

For one-liner-lovers

对于单线爱好者

If you are one-liner-loverlike me, what you're asking would be what my resize_array_rightdoes.

如果你和我一样是单线爱好者,你问的就是我的resize_array_right



const resize_array_left = (array, length, fill_with) => (new Array(length)).fill(fill_with).concat(array).slice(-length);
// Pads left when expanding an array.
// Put left elements first to be removed when shrinking an array.

const resize_array_right = (array, length, fill_with) => array.concat((new Array(length)).fill(fill_with)).slice(0, length);
// Pads right when expanding an array.
// Put right elements first to be removed when shrinking an array.

You can find it out in NPM, as resize-array.

您可以在NPM 中找到它,如resize-array.



Browser compatibility

浏览器兼容性

  • Chrome: 45 and above.
  • Firefox: 31 and above.
  • Internet Explorer: ?.
  • Edge: ?.
  • 铬:45 及以上。
  • 火狐:31 及以上。
  • IE浏览器: ?。
  • 边缘: ?。