如何在 JavaScript 中的数组开头添加新的数组元素?
Posted
技术标签:
【中文标题】如何在 JavaScript 中的数组开头添加新的数组元素?【英文标题】:How can I add new array elements at the beginning of an array in JavaScript? 【发布时间】:2011-12-25 19:09:00 【问题描述】:我需要在数组的开头添加或添加元素。
例如,如果我的数组如下所示:
[23, 45, 12, 67]
我的 AJAX 调用的响应是 34
,我希望更新后的数组如下所示:
[34, 23, 45, 12, 67]
目前我打算这样做:
var newArray = [];
newArray.push(response);
for (var i = 0; i < theArray.length; i++)
newArray.push(theArray[i]);
theArray = newArray;
delete newArray;
有没有更好的方法来做到这一点? javascript 是否有任何内置功能可以做到这一点?
我的方法的复杂度是O(n)
,看到更好的实现会很有趣。
【问题讨论】:
仅供参考:如果您需要在数组的开头连续插入一个元素,使用push
语句然后调用reverse
会更快,而不是调用unshift
all时间。
@JennyO'Reilly 您应该将此作为答案发布。完美匹配我的用例。谢谢
性能测试:jsperf.com/adding-element-to-the-array-start 但是每个浏览器的结果都不同。
【参考方案1】:
"array.unshift()" 是一种用于在数组开头添加元素的方法。
该指南在下面的链接中。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift
let array = [23, 45, 12, 67];
array.unshift(12);
console.log(array);
【讨论】:
【参考方案2】:您可以反转数组并推送数据。最后,再次反转它:
var arr = [2, 3, 4, 5, 6];
var arr2 = 1;
arr.reverse();
//[6, 5, 4, 3,2]
arr.push(arr2);
【讨论】:
你可以这样做,但你永远也不应该这样做。这是非常低效和不必要的。【参考方案3】:如果要将数组中的元素推送到数组的开头,请使用<func>.apply(<this>, <Array of args>)
:
const arr = [1, 2];
arr.unshift.apply(arr, [3, 4]);
console.log(arr); // [3, 4, 1, 2]
【讨论】:
【参考方案4】:使用 ES6 destructuring(避免原始数组的突变):
const newArr = [item, ...oldArr]
【讨论】:
基本上是the one by Abdennour TOUMI的重复答案...【参考方案5】:在 ES6 中,使用扩展运算符...
:
演示
var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]
console.log(arr)
【讨论】:
还创建了一个新数组,对纯函数很有用 这里的性能含义是什么?它比使用 unshift() 慢吗? 当然,它会更慢,因为它是一个不可变数组(创建一个新数组)。如果您正在使用大型阵列或性能是您的首要要求,请考虑改用concat
。
2018年性能不重要,新版本在浏览器和节点中获得相同的性能
@AbdennourTOUMI 只是为了澄清您的评论。它不是创建一个不可变数组,它只是创建一个新数组而不改变现有数组。【参考方案6】:
另一种方法是通过concat
:
var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));
concat
和unshift
的区别在于concat
返回一个新数组。他们之间的表现可以在here找到。
function fn_unshift()
arr.unshift(0);
return arr;
function fn_concat_init()
return [0].concat(arr)
这是测试结果:
【讨论】:
除了添加参考之外,附加两者的性能比较对您的回答会有好处。 我刚收到 jsPerf 在我们发布 v2 时暂时不可用。请稍后通过链接重试。包含结果而不是链接到它们的另一个很好的理由。 jsPref 结果:unshift
:25,510 ±3.18% 慢 99% concat
:2,436,894 ±3.39% 最快
在最新的 Safari 中,fn_unshift() 运行速度更快。
在最新的 Safari (v 10) 中,fn_unshift() 再次变慢了。【参考方案7】:
你有一个数组:var arr = [23, 45, 12, 67];
要将项目添加到开头,您想使用splice
:
var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);
【讨论】:
arr.splice(0, arr.length, 34); @LiorElrom 你的 sn-p 是做什么的? @poushy 它是特定于浏览器的,在 Firefox 54 中unshift
快 50%(但大多数情况下更具可读性)
@poushy 不再。慢得多。【参考方案8】:
没有变异
实际上,所有unshift
/push
和shift
/pop
变异源数组。
unshift
/push
从开始/结束向现有数组添加一项,shift
/pop
从数组的开始/结束删除一项。
但是有几种方法可以在没有突变的情况下将项目添加到数组中。结果是一个新数组,要添加到数组末尾,请使用以下代码:
const originArray = ['one', 'two', 'three'];
const newItem = 4;
const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+
要添加到原始数组的开头,请使用以下代码:
const originArray = ['one', 'two', 'three'];
const newItem = 0;
const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+
通过上述方式,您可以在没有突变的情况下添加到数组的开头/结尾。
【讨论】:
我只是在originArray
的末尾放了一个slice
函数,以防止它的可变性。
太棒了!谈到(Redux)状态管理......这个答案很宝贵!
[newItem, ...originArray]; // ES6+ 是很棒的语法!工作完美!谢谢。【参考方案9】:
使用unshift
。类似于push
,只是它将元素添加到数组的开头而不是结尾。
unshift
/push
- 在数组的开头/结尾添加一个元素
shift
/pop
- 删除并返回数组的第一个/最后一个元素
一个简单的图表...
unshift -> array <- push
shift <- array -> pop
和图表:
add remove start end
push X X
pop X X
unshift X X
shift X X
查看MDN Array documentation。几乎每一种能够从数组中推送/弹出元素的语言也都能够取消移位/移位(有时称为push_front
/pop_front
)元素,您永远不必自己实现这些。
正如 cmets 中所指出的,如果您想避免改变原始数组,可以使用 concat
,它将两个或多个数组连接在一起。您可以使用它在功能上将单个元素推送到现有数组的前面或后面;为此,您需要将新元素转换为单个元素数组:
const array = [3, 2, 1]
const newFirstElement = 4
const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]
console.log(newArray);
concat
也可以附加项目。 concat
的参数可以是任何类型;如果它们还不是数组,则它们被隐式包装在单元素数组中:
const array = [3, 2, 1]
const newLastElement = 0
// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement) // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]
console.log(newArray1);
console.log(newArray2);
【讨论】:
使用concat
可能更可取,因为它会返回新数组。对于链接非常有用。 [thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)
等...如果您使用 unshift
,则无法进行链接,因为您得到的只是长度。
移位/取消移位、推/弹出、拼接。这些方法的名称非常合乎逻辑。【参考方案10】:
将新元素添加到数组中的备忘单
1. Array#unshift
const list = [23, 45, 12, 67];
list.unshift(34);
console.log(list); // [34, 23, 45, 12, 67];
2。 Array#splice
const list = [23, 45, 12, 67];
list.splice(0, 0, 34);
console.log(list); // [34, 23, 45, 12, 67];
3. ES6 spread...
const list = [23, 45, 12, 67];
const newList = [34, ...list];
console.log(newList); // [34, 23, 45, 12, 67];
4. Array#concat
const list = [23, 45, 12, 67];
const newList = [32].concat(list);
console.log(newList); // [34, 23, 45, 12, 67];
注意:在每个示例中,您都可以通过提供更多要插入的项目来前置多个项目。
【讨论】:
【参考方案11】:使用splice
,我们在数组的开头插入一个元素:
arrName.splice( 0, 0, 'newName1' );
【讨论】:
【参考方案12】:如果您需要在数组的开头连续插入一个元素,使用push
语句然后调用reverse
会更快,而不是一直调用unshift
。
基准测试: http://jsben.ch/kLIYf
【讨论】:
注意:初始数组应该为空。 在 2021 年,您的基准测试显示unshift
在所有主要桌面浏览器(至少在此 Mac 上)的全面胜利。
@OllyHodgson 在 Ubuntu Linux 上使用 Firefox 进行测试:反向解决方案快 3 倍。【参考方案13】:
var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]
【讨论】:
人们之所以需要 4 个日常使用的函数的可视化指南,是因为函数名称被加密... 为什么 unshift 不叫 Insert?班次应该是删除。等等…… //为什么unshift不叫Insert?//它来自C编程语言的约定,其中数组元素被视为堆栈。 (完整的解释见perlmonks.org/?node_id=613129) @Pascal 不,插入和删除将是特别糟糕的名称;它们意味着随机访问,而不是从数组的前面添加/删除 我原以为 unshift 应该删除第一个键,而 shift 会插入第一个键,但这只是我的一般想法 请注意[23, 45, 12, 67].unshift(34)
将不起作用。数组必须首先保存在变量中,因为unshift
本身返回一个值。【参考方案14】:
快速备忘单:
术语 shift/unshift 和 push/pop 可能有点令人困惑,至少对于可能不熟悉 C 编程的人来说。
如果您不熟悉行话,这里有一个替代术语的快速翻译,可能更容易记住:
* array_unshift() - (aka Prepend ;; InsertBefore ;; InsertAtBegin )
* array_shift() - (aka UnPrepend ;; RemoveBefore ;; RemoveFromBegin )
* array_push() - (aka Append ;; InsertAfter ;; InsertAtEnd )
* array_pop() - (aka UnAppend ;; RemoveAfter ;; RemoveFromEnd )
【讨论】:
以上是关于如何在 JavaScript 中的数组开头添加新的数组元素?的主要内容,如果未能解决你的问题,请参考以下文章