如何将项目插入到特定索引处的数组中(JavaScript)

问题描述:

我正在寻找一种 JavaScript 数组插入方法,其样式为:

arr.insert(index, item)

最好在 jQuery 中,但此时任何 JavaScript 实现都可以。

解决方案1:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

您希望在原生数组对象上使用 splice 函数。

arr.splice(index, 0, item); 将在指定的 index 处将 item 插入到 arr 中(首先删除 0 项,即它只是一个插入)。

在此示例中,我们将创建一个数组并将一个元素添加到索引 2 中:

var arr = []; arr[0] = “贾尼”; arr[1] = “黑格”; arr[2] = “陈旧”; arr[3] = “凯吉姆”; arr[4] = “博尔赫”;控制台.log(arr.join()); // Jani,Hege,Stale,Kai Jim,Borge arr.splice(2, 0, “Lene”);控制台.log(arr.join()); // Jani,Hege,Lene,Stale,Kai Jim,Borge

谢谢,我以为我会觉得问起来很愚蠢,但现在我知道答案了,我不知道!当一个更易于搜索的术语普遍用于相同的功能时,他们到底为什么决定将其称为拼接?!

@tags2k:因为该函数不仅仅是插入项目,而且它的名称已经在 perl 中建立了?

文档:developer.mozilla.org/en/JavaScript/Guide/…

拼接可以插入,但经常不能。例如:arr.splice(2,3) 将删除从索引 2 开始的 3 个元素。如果不传递第 3 个....第 N 个参数,则不会插入任何内容。所以名称 insert() 也不公平。

我认为“拼接”这个词是有道理的。拼接意味着加入或连接,也意味着改变。您有一个已建立的数组,您现在正在“更改”这将涉及添加或删除元素。您指定数组中从哪里开始,然后指定要删除多少旧项目(如果有),最后,可以选择要添加的新元素列表。拼接当然也是一个很棒的科幻术语。

解决方案2:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

您可以通过执行以下操作来实现 Array.insert 方法:

Array.prototype.insert = function ( index, item ) {
    this.splice( index, 0, item );
};

然后你可以像这样使用它:

var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');

// => arr == [ 'A', 'B', 'C', 'D', 'E' ]

要插入多个项目,您可以使用 Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }

向数组添加内容的问题在于,当您执行 for(i in arr) {...} 时,该函数将显示为一个元素

但请记住,不建议扩展本机类型,因为它可能会干扰其他代码或未来的功能。

不要修改你不拥有的对象

不要修改原型

解决方案3:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

除了拼接之外,您可以使用这种不会改变原始数组的方法,但它会创建一个包含添加项的新数组。当您需要避免突变时,它很有用。我在这里使用 ES6 扩展运算符。

const items = [1, 2, 3, 4, 5] const insert = (arr, index, newItem) => [ // 指定索引之前的部分数组 …arr.slice(0, index),/ / 插入项 newItem, // 指定索引之后的数组部分 …arr.slice(index) ] const result = insert(items, 1, 10) console.log(result) // [1, 10, 2 , 3, 4, 5]

这可用于通过稍微调整函数以将 rest 运算符用于新项目来添加多个项目,并将其传播到返回的结果中:

const items = [1, 2, 3, 4, 5] const insert = (arr, index, …newItems) => [ // 指定索引之前的部分数组 …arr.slice(0, index ), // 插入的项目 …newItems, // 指定索引之后的数组部分 …arr.slice(index) ] const result = insert(items, 1, 10, 20) console.log(result) // [1, 10, 20, 2, 3, 4, 5]

这是一个好的、安全的方法吗?我问是因为这看起来如此优雅和简洁,但没有其他答案涉及这一点。他们中的大多数都修改了原型对象!

@HarshKanchina这可能是因为大多数答案都是ES6之前的,但是根据我的经验,这种方法现在很常见

这种方法总是比拼接更慢更糟糕。不要被漂亮的糖语法或其他被误导的开发人员中的流行所迷惑(*cough* gafi *cough*)。分配一个全新的数组并丢弃旧数组比修改原始数组要慢得多。如果您需要一份副本,请在 splice() 之前调用 slice()。永远不要将 ES6 用于如此琐碎的事情,这些事情可以用其他 API 做得更好、更干净。

你应该解释为什么你应该避免突变。慢吗?如果是这样,慢多少?额外的“麻烦”值得吗?

@JackG 不要忘记 slice() 将分配一个新数组,实际上,splice() 也会分配一个新数组,因为它返回一个包含已删除项目的数组(在这种情况下为空数组)。在这些情况下运行基准测试表明拼接更快(约 30%),但我们处于每秒数百万次操作的范围内,因此除非您的应用程序正在执行 大量 此类操作在一个紧密的循环中,它不会有任何区别。

解决方案4:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

自定义数组插入方法

1.具有多个参数和链接支持

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    this.splice.apply(this, [index, 0].concat(
        Array.prototype.slice.call(arguments, 1)));
    return this;
};

它可以插入多个元素(与原生 splice 一样)并支持链接:

["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]

2.具有数组类型参数合并和链接支持

/* Syntax:
   array.insert(index, value1, value2, ..., valueN) */

Array.prototype.insert = function(index) {
    index = Math.min(index, this.length);
    arguments.length > 1
        && this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
        && this.insert.apply(this, arguments);
    return this;
};

它可以将参数中的数组与给定数组合并,还支持链接:

["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"

演示: http://jsfiddle.net/UPphH/

有没有一种紧凑的方法可以让这个版本在参数中找到一个数组时也合并一个数组?

我不明白第一个结果 ["b", "X", "Y", "Z", "c"]。为什么不包括 "d"?在我看来,如果您将 6 作为 slice() 的第二个参数,并且数组中有 6 个元素从指定的索引开始,那么您应该在返回值中获得所有 6 个元素。 (文档说该参数为 howMany。)developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

实际上,如果我使用 3 或更多的索引,我在输出中什么也得不到(案例 1.,FireFox)["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3); => [ ]

@AlexisWilke 在第一个示例中,我使用了 slice 方法,而不是您在评论中提到的 splice。 slice 的第二个参数(名为 end)是 结束提取的从零开始的索引。 slice 提取最多但不包括 end。因此,在 insert 之后有 ["a", "b", "X", "Y", "Z", "c", "d"],slice 从中提取索引从 1 到 6 的元素,即从 "b" 到 "d" 但不包括 "d"。是否有意义?

出于某种原因,当我使用 insert2 时,我得到一个“预期 1 个参数,但得到 2 个”异常。

解决方案5:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

如果您想一次将多个元素插入到数组中,请查看此 Stack Overflow 答案:A better way to splice an array into an array in javascript

这里还有一些函数来说明这两个例子:

function insertAt(array, index) {
    var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
    return insertArrayAt(array, index, arrayToInsert);
}

function insertArrayAt(array, index, arrayToInsert) {
    Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
    return array;
}

最后是一个 jsFiddle,您可以自己查看:http://jsfiddle.net/luisperezphd/Wc8aS/

这就是您使用这些功能的方式:

// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");

// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);

insertAt() 创建单元素arrayToInsert 后调用insertArrayAt() 会不会更好?这样可以避免重复相同的代码。

这是何时使用“应用”的一个很好的例子

我在这个方法中添加了一个 removeCount 参数,以利用 splice 的能力来删除该索引处的项目: Array.prototype.splice.apply(array, [index, removeCount || 0].concat(arrayToInsert));

解决方案6:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

对于正确的函数式编程和链接目的,Array.prototype.insert() 的发明是必不可少的。实际上,如果 splice 返回的是变异数组而不是完全没有意义的空数组,它可能是完美的。所以这里是:

Array.prototype.insert = function(i,…rest){ this.splice(i,0,…rest) return this } var a = [3,4,8,9]; document.write(“” + JSON.stringify(a.insert(2,5,6,7)) + “”);

好吧,上面的 Array.prototype.splice() 会改变原始数组,有些人可能会抱怨“你不应该修改不属于你的东西”,这也可能是正确的。所以为了公益,我想再给一个不改变原数组的Array.prototype.insert()。来了;

Array.prototype.insert = function(i,…rest){ return this.slice(0,i).concat(rest,this.slice(i)); } var a = [3,4,8,9], b = a.insert(2,5,6,7); console.log(JSON.stringify(a)); console.log(JSON.stringify(b));

“一个完全没有意义的空数组” - 它仅在第二个参数为 0 时返回一个空数组。如果它大于 0,则返回从数组中删除的项。鉴于您要添加到原型,并且 splice 改变了原始数组,我认为“正确的函数式编程”不属于 splice 附近的任何地方。

我们在这里讨论的是插入,Array.prototype.splice() 的第二个参数必须为零。它返回的内容除了“我没有删除任何东西”之外没有任何意义,因为我们用它来插入一个项目,所以我们已经有了这些信息。如果您不想改变原始数组,那么您可以使用两个 Array.prototype.slice() 和一个 Array.prototype.concat() 操作来做同样的事情。由你决定。

您的第二个实现是整个页面中最干净的,您的投票数为零。请拿走我的,继续做好工作。 (你应该避免改变原型,但你已经知道了)

我认为值得一提的是,其余参数是新的 ECMA 6th (developer.mozilla.org/en/docs/Web/JavaScript/Reference/…)

解决方案7:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

解决方案与性能

今天(2020.04.24)我为大小阵列选择的解决方案进行测试。我在 Chrome 81.0、Safari 13.1 和 Firefox 75.0 上的 macOS v10.13.6 (High Sierra) 上对它们进行了测试。

结论

适用于所有浏览器

令人惊讶的是,对于小型阵列,基于 slice 和 reduce (D,E,F) 的非就地解决方案通常比就地解决方案快 10 倍至 100 倍

对于大型阵列,基于拼接(AI、BI 和 CI)的就地解决方案最快(有时约为 100 倍 - 但取决于阵列大小)

对于小型阵列,BI 解决方案最慢

对于大阵列,E 解决方案最慢

https://i.stack.imgur.com/gZjhH.png

细节

测试分为两组:就地解决方案(AI、BI 和 CI)和非就地解决方案(D、E 和 F),并针对两种情况进行:

测试一个有 10 个元素的数组 - 你可以在这里运行它

测试一个包含 1,000,000 个元素的数组 - 你可以在这里运行它

测试代码显示在以下代码段中:

jsfiddle

函数 AI(arr, i, el) { arr.splice(i, 0, el);返回 arr; } 函数 BI(arr, i, el) { Array.prototype.splice.apply(arr, [i, 0, el]);返回 arr; } 函数 CI(arr, i, el) { Array.prototype.splice.call(arr, i, 0, el);返回 arr; } 函数 D(arr, i, el) { return arr.slice(0, i).concat(el, arr.slice(i)); } 函数 E(arr, i, el) { 返回 […arr.slice(0, i), el, …arr.slice(i)] } 函数 F(arr, i, el) { 返回 arr .reduce((s, a, j)=> (ji ? s.push(a) : s.push(el, a), s), []); } // ------------- // 测试 // ------------- 让 arr = [“a”, “b”, “c”, “d”、“e”、“f”];让 log = (n, f) => { 让 a = f([…arr], 3, “NEW”); console.log(${n}: [${a}]); };日志(“人工智能”,人工智能);日志(‘BI’,BI);日志(‘CI’,CI);日志(‘D’,D);日志(‘E’,E);日志(‘F’,F);此代码段仅显示经过测试的代码(它不执行测试)

Google Chrome 上的小数组的示例结果如下:

https://i.stack.imgur.com/cS1YZ.png

答案没有解决OP的问题。

@kabirbaidhya 实际上在这个答案中你可以找到很多 OP 问题的解决方案,但是这个答案的附加价值是它们之间的性能比较 - 我希望很多人会发现它很有用

也许,您可能想要稍微调整一下您的答案,以便用户可以直观地首先看到可能的解决方案,然后再看到它们对性能的影响。它看起来主要关注性能 rn。

解决方案8:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

使用 Array.prototype.splice() 是实现它的简单方法

const numbers = [‘one’, ‘two’, ‘four’, ‘five’] numbers.splice(2, 0, ‘three’);控制台日志(数字)

详细了解 Array.prototype.splice() here

解决方案9:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

在这种情况下,我建议使用纯 JavaScript。 JavaScript 中也没有任何插入方法,但我们有一个方法是内置的 Array 方法,它可以为您完成这项工作。这叫拼接…

让我们看看什么是 splice()…

splice() 方法通过删除现有元素和/或添加新元素来更改数组的内容。

好的,假设我们在下面有这个数组:

const arr = [1, 2, 3, 4, 5];

我们可以像这样删除 3:

arr.splice(arr.indexOf(3), 1);

它将返回 3,但如果我们现在检查 arr,我们有:

[1, 2, 4, 5]

到目前为止,一切都很好,但是我们如何使用拼接将新元素添加到数组中?

让我们把3放回arr中…

arr.splice(2, 0, 3);

让我们看看我们做了什么…

我们再次使用 splice,但是这次对于第二个参数,我们传递了 0,这意味着我们不想删除任何项目,但同时,我们添加了第三个参数,即将添加到第二个索引处的 3 …

您应该知道我们可以同时删除和添加。例如,现在我们可以这样做:

arr.splice(2, 2, 3);

这将删除索引 2 处的两个项目。然后在索引 2 处添加 3,结果将是:

[1, 2, 3, 5];

这显示了拼接中的每个项目是如何工作的:

array.splice(开始, deleteCount, item1, item2, item3 …)

感谢您在未来进行解释,我建议对数组值使用非数字数字,以显示示例。例如:arr.splice(2, 0, 3) 与 arr.splice(2, 0, "C")。读者更容易理解哪个参数映射到值部分,哪个参数映射到索引部分。谢谢!

解决方案10:

huntsbot.com – 高效赚钱,自由工作

这里有两种方法:

常量数组 = [‘我的’,‘名字’,‘Hamza’]; array.splice(2, 0, ‘是’); console.log(“方法一:”, array.join(" "));

或者

Array.prototype.insert = function (index, item) { this.splice(index, 0, item); };常量数组 = [‘我的’,‘名字’,‘Hamza’]; array.insert(2, ‘是’); console.log(“方法二:”, array.join(“”));

解决方案11:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

在特定索引处附加单个元素

// Append at a specific position (here at index 1)
arrName.splice(1, 0,'newName1');
// 1: index number, 0: number of element to remove, newName1: new element


// Append at a specific position (here at index 3)
arrName[3] = 'newName1';

在特定索引处附加多个元素

// Append from index number 1
arrName.splice(1, 0, 'newElemenet1', 'newElemenet2', 'newElemenet3');
// 1: index number from where append start,
// 0: number of element to remove,
//newElemenet1,2,3: new elements

值得注意的是 arrName[3] 不会附加,它会覆盖。

它将元素添加到现有数组中而不是覆盖,例如:let arrName = ['xxx', 'yyy', 'zzz']; arrName.splice(1, 0,'aaa', 'bbb', 'ccc');打印 arrName 后

如果 arrName 有超过 3 个元素,则您将覆盖第 3 个元素,而不是附加。还是我看错了?

如果我们在中间插入一个元素,它会移动下一个元素而不是覆盖。请说明您的问题,您需要什么。拿一个数组(例子)和你需要的输出。请评论我

如果数组只有 3 个元素,@Srikrushna arrName[3] = 'newName1'; 将追加。如果索引 3 中有一个元素,它将被替换。如果要在末尾追加,最好使用 arrName.push('newName1');

原文链接:https://www.huntsbot.com/qa/QQDv/how-to-insert-an-item-into-an-array-at-a-specific-index-javascript?lang=zh_CN

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值