Javascript 将值添加到数组的最有效方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6195729/
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 20:41:41  来源:igfitidea点击:

Most efficient way to prepend a value to an array

javascriptarraysprepend

提问by samccone

Assuming I have an array that has a size of N(where N > 0), is there a more efficient way of prepending to the array that would not require O(N + 1) steps?

假设我有一个大小为N(where N > 0)的数组,是否有更有效的方法来添加不需要 O(N + 1) 步的数组?

In code, essentially, what I currently am doing is

在代码中,本质上,我目前正在做的是

function prependArray(value, oldArray) {
  var newArray = new Array(value);

  for(var i = 0; i < oldArray.length; ++i) {
    newArray.push(oldArray[i]);
  }

  return newArray;
}

回答by maerics

I'm not sure about more efficient in terms of big-O but certainly using the unshiftmethod is more concise:

我不确定在 big-O 方面更有效,但肯定使用该unshift方法更简洁:

var a = [1, 2, 3, 4];
a.unshift(0);
a; // => [0, 1, 2, 3, 4]

[Edit]

[编辑]

This jsPerf benchmarkshows that unshiftis decently faster in at least a couple of browsers, regardless of possibly different big-O performance ifyou are ok with modifying the array in-place. If you really can't mutate the original array then you would do something like the below snippet, which doesn't seem to be appreciably faster than your solution:

这个jsPerf 基准测试表明,如果您可以就地修改数组,那么unshift至少在几个浏览器中要快得多,而不管可能不同的大 O 性能。如果您真的无法改变原始数组,那么您可以执行以下代码段之类的操作,这似乎并不比您的解决方案快得多:

a.slice().unshift(0); // Use "slice" to avoid mutating "a".

[Edit 2]

[编辑 2]

For completeness, the following function can be used instead of OP's example prependArray(...)to take advantage of the Array unshift(...)method:

为了完整起见,可以使用以下函数代替 OP 的示例prependArray(...)来利用 Arrayunshift(...)方法:

function prepend(value, array) {
  var newArray = array.slice();
  newArray.unshift(value);
  return newArray;
}

var x = [1, 2, 3];
var y = prepend(0, x);
y; // => [0, 1, 2, 3];
x; // => [1, 2, 3];

回答by Frank Tan

With ES6, you can now use the spread operatorto create a new array with your new elements inserted before the original elements.

在 ES6 中,您现在可以使用展开运算符创建一个新数组,并将新元素插入到原始元素之前。

// Prepend a single item.
const a = [1, 2, 3];
console.log([0, ...a]);

// Prepend an array.
const a = [2, 3];
const b = [0, 1];
console.log([...b, ...a]);

Update 2018-08-17: Performance

2018-08-17 更新:性能

I intended this answer to present an alternative syntax that I think is more memorable and concise. It should be noted that according to some benchmarks (see this other answer), this syntax is significantly slower. This is probably not going to matter unless you are doing many of these operations in a loop.

我打算在这个答案中提出一种我认为更令人难忘和简洁的替代语法。应该注意的是,根据一些基准测试(参见其他答案),这种语法要慢得多。除非您在循环中执行许多这些操作,否则这可能无关紧要。

回答by mgiuca

If you are prepending an array to the front of another array, it is more efficient to just use concat. So:

如果您将一个数组添加到另一个数组的前面,则仅使用concat. 所以:

var newArray = values.concat(oldArray);

But this will still be O(N) in the size of oldArray. Still, it is more efficient than manually iterating over oldArray. Also, depending on the details, it may help you, because if you are going to prepend many values, it's better to put them into an array first and then concat oldArray on the end, rather than prepending each one individually.

但这仍然是 oldArray 大小的 O(N)。尽管如此,它还是比手动迭代 oldArray 更有效。此外,根据细节,它可能对您有所帮助,因为如果您要添加许多值,最好先将它们放入一个数组中,然后在最后连接 oldArray,而不是单独添加每个值。

There's no way to do better than O(N) in the size of oldArray, because arrays are stored in contiguous memory with the first element in a fixed position. If you want to insert before the first element, you need to move all the other elements. If you need a way around this, do what @GWW said and use a linked list, or a different data structure.

在 oldArray 的大小上,没有比 O(N) 更好的方法了,因为数组存储在连续内存中,第一个元素位于固定位置。如果要在第一个元素之前插入,则需要移动所有其他元素。如果您需要解决此问题的方法,请按照@GWW 所说的进行操作并使用链表或不同的数据结构。

回答by uroslates

If you would like to prepend array (a1 with an array a2) you could use the following:

如果您想添加数组(a1 与数组 a2),您可以使用以下命令:

var a1 = [1, 2];
var a2 = [3, 4];
Array.prototype.unshift.apply(a1, a2);
console.log(a1);
// => [3, 4, 1, 2]

回答by kennebec

f you need to preserve the old array, slice the old one and unshift the new value(s) to the beginning of the slice.

如果您需要保留旧数组,请将旧数组切片并将新值移至切片的开头。

var oldA=[4,5,6];
newA=oldA.slice(0);
newA.unshift(1,2,3)

oldA+'\n'+newA

/*  returned value:
4,5,6
1,2,3,4,5,6
*/

回答by John Klimov

I have some fresh tests of different methods of prepending. For small arrays (<1000 elems) the leader is for cycle coupled with a push method. For huge arrays, Unshift method becomes the leader.

我对不同的前置方法进行了一些新的测试。对于小数组(<1000 elems),leader 用于循环加上推送方法。对于庞大的数组,Unshift 方法成为领导者。

But this situation is actual only for Chrome browser. In Firefox unshift has an awesome optimization and is faster in all cases.

但这种情况仅适用于 Chrome 浏览器。在 Firefox 中 unshift 有一个很棒的优化并且在所有情况下都更快。

ES6 spread is 100+ times slower in all browsers.

ES6 在所有浏览器中的传播速度要慢 100 多倍。

https://jsbench.me/cgjfc79bgx/1

https://jsbench.me/cgjfc79bgx/1

回答by bjornd

There is special method:

有一个特殊的方法:

a.unshift(value);

But if you want to prepend several elements to array it would be faster to use such a method:

但是如果你想在数组中添加几个元素,使用这样的方法会更快:

var a = [1, 2, 3],
    b = [4, 5];

function prependArray(a, b) {
    var args = b;
    args.unshift(0);
    args.unshift(0);
    Array.prototype.splice.apply(a, args);
}

prependArray(a, b);
console.log(a); // -> [4, 5, 1, 2, 3]

回答by Miguel Mota

Example of prepending in-place:

就地前置示例:

var A = [7,8,9]
var B = [1,2,3]

A.unshift(...B)

console.log(A) // [1,2,3,7,8,9]

回答by rehman_00001

Calling unshiftonly returns the length of the new array. So, to add an element in the beginning and to return a new array, I did this:

调用unshift只返回新数组的长度。因此,要在开头添加一个元素并返回一个新数组,我这样做了:

let newVal = 'someValue';
let array = ['hello', 'world'];
[ newVal ].concat(array);

or simply with spread operator:

或者简单地使用扩展运算符:

[ newVal, ...array ]

This way, the original array remains untouched.

这样,原始数组保持不变。