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

我正在寻找一个JavaScript数组插入方法,风格为:

arr.insert(index, item)

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

3127701 次浏览

您需要本机数组对象上的#0函数。

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

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

var arr = [];arr[0] = "Jani";arr[1] = "Hege";arr[2] = "Stale";arr[3] = "Kai Jim";arr[4] = "Borge";
console.log(arr.join()); // Jani,Hege,Stale,Kai Jim,Borgearr.splice(2, 0, "Lene");console.log(arr.join()); // Jani,Hege,Lene,Stale,Kai Jim,Borge

如果您想一次将多个元素插入数组中,请查看此Stack Overflow答案:在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);

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

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

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

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

自定义数组insert方法

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

它可以插入多个元素(正如原生#0所做的那样)并支持链接:

["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/

即使这个问题已经得到了回答,我还是添加了这个注释作为替代方法。

我想将已知数的项目放入数组中,放入特定位置,因为它们来自“关联数组”(即对象),根据定义,该数组不能保证按排序顺序排列。我希望生成的数组是一个对象数组,但对象在数组中以特定顺序排列,因为数组保证了它们的顺序。所以我这样做了。

首先是源对象,从PostgreSQL检索的JSONB字符串。我想让它按每个子对象中的“order”属性排序。

var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';
var jsonb_obj = JSON.parse(jsonb_str);

由于对象中的节点数量是已知的,我首先创建一个具有指定长度的数组:

var obj_length = Object.keys(jsonb_obj).length;var sorted_array = new Array(obj_length);

然后迭代对象,将新创建的临时对象放置到数组中所需的位置,而不进行任何“排序”。

for (var key of Object.keys(jsonb_obj)) {var tobj = {};tobj[key] = jsonb_obj[key].abbr;
var position = jsonb_obj[key].order - 1;sorted_array[position] = tobj;}
console.dir(sorted_array);

为了正确的函数式编程和链接目的,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("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");

嗯,好吧,上面的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));

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

const items = [1, 2, 3, 4, 5]
const insert = (arr, index, newItem) => [// part of the array before the specified index...arr.slice(0, index),// inserted itemnewItem,// part of the array after the specified index...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) => [// part of the array before the specified index...arr.slice(0, index),// inserted items...newItems,// part of the array after the specified index...arr.slice(index)]
const result = insert(items, 1, 10, 20)
console.log(result)// [1, 10, 20, 2, 3, 4, 5]

我试过这个,它工作得很好!

var initialArr = ["India","China","Japan","USA"];initialArr.splice(index, 0, item);

索引是要插入或删除元素的位置。

0,即第二个参数,定义要从索引中删除的元素数。item包含您要在数组中创建的新条目。它可以是一个或多个。

initialArr.splice(2, 0, "Nigeria");initialArr.splice(2, 0, "Australia","UK");

另一种可能的解决方案,使用Array.reduce

const arr = ["apple", "orange", "raspberry"];const arr2 = [1, 2, 4];
const insert = (arr, item, index) =>arr.reduce(function(s, a, i) {i === index ? s.push(item, a) : s.push(a);return s;}, []);
console.log(insert(arr, "banana", 1));console.log(insert(arr2, 3, 2))

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

让我们看看拼接是什么。

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

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

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

我们可以像这样删除3

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

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

[1, 2, 4, 5]

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

让我们把三个放回去…

arr.splice(2, 0, 3);

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

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

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

arr.splice(2, 2, 3);

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

[1, 2, 3, 5];

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

array.splice(start, deleteCount, item1, item2, item3…)

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

// 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 1arrName.splice(1, 0, 'newElemenet1', 'newElemenet2', 'newElemenet3');// 1: index number from where append start,// 0: number of element to remove,//newElemenet1,2,3: new elements

任何仍然对此有问题,并且尝试了以前答案中的所有选项但从未得到它的人。我分享我的解决方案,这是考虑到你不想显式声明对象与数组的属性。

function isIdentical(left, right){return JSON.stringify(left) === JSON.stringify(right);}
function contains(array, obj){let count = 0;array.map((cur) => {if(this.isIdentical(cur, obj))count++;});return count > 0;}

这是迭代引用数组并将其与您要检查的对象进行比较的组合,将它们都转换为字符串,然后在匹配时迭代。然后您可以计数。这可以改进,但这是我解决的地方。

减少方法的利润如下:

function insert(arr, val, index) {return index >= arr.length? arr.concat(val): arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);}

因此,通过这种方式,我们可以返回一个新数组(这将是一个很酷的函数式方法-比使用推送拼接要好得多),其中元素插入在索引处,如果索引大于数组的长度,它将插入在末尾。

这是我在一个应用程序中使用的一个工作函数。

这将检查项目是否存在:

let ifExist = (item, strings = [ '' ], position = 0) => {// Output into an array with an empty string. Important just in case their isn't any item.let output = [ '' ];// Check to see if the item that will be positioned exist.if (item) {// Output should be equal to an array of strings.output = strings;// Use splice() in order to break the array.// Use positional parameters to state where to put the item// and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position.output.splice(position, 0, item);}// Empty string is so we do not concatenate with comma or anything else.return output.join("");};

然后我叫它下面。

ifExist("friends", [ ' ( ', ' )' ], 1)}  // Output: ( friends )ifExist("friends", [ ' - '], 1)}  // Output:  - friendsifExist("friends", [ ':'], 0)}  // Output:   friends:

我必须同意Redu的回答,因为plice()肯定有一点令人困惑的接口。cdbajorin给出的响应“它只在第二个参数为0时返回一个空数组。如果它大于0,它返回从数组中删除的项目”虽然准确,但证明了这一点。

该函数的目的是拼接,或者如Jakob Keller之前所说,“加入或连接,也改变。

你有一个已建立的数组,你现在正在更改它,这将涉及添加或删除元素……"鉴于此,被删除的元素的返回值(如果有的话)充其量是尴尬的。而且我100%同意,如果这种方法返回了看起来很自然的东西,一个添加了拼接元素的新数组,它可能更适合链接。然后你可以对返回的数组执行["19","17"]. plice(1,0,"18"). join("…")或任何你喜欢的操作。

它返回被删除的内容这一事实只是胡说八道。如果该方法的意图是“裁剪一组元素”,这是它唯一的意图,也许吧。如果我不知道我已经裁剪了什么,我可能没有理由裁剪这些元素,不是吗?

如果它的行为像concat()、map()、duce()、SLACH()等,其中从现有数组生成新数组而不是改变现有数组,那会更好。这些都是可链接的,是一个重要的问题。链式数组操作相当常见。

似乎语言需要朝着一个或另一个方向前进,并尽可能坚持下去。JavaScript是功能性的,不那么声明性,这似乎是对规范的奇怪偏离。

这里有两种方法:

const array = [ 'My', 'name', 'Hamza' ];
array.splice(2, 0, 'is');
console.log("Method 1: ", array.join(" "));

Array.prototype.insert = function ( index, item ) {this.splice( index, 0, item );};
const array = [ 'My', 'name', 'Hamza' ];array.insert(2, 'is');
console.log("Method 2 : ", array.join(" "));

#0是要走的路,除非你真的想避免改变数组。给定2个数组arr1arr2,以下是在第一个元素之后将arr2的内容插入arr1的方式:

const arr1 = ['a', 'd', 'e'];const arr2 = ['b', 'c'];
arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']
console.log(arr1)

如果您担心改变数组(例如,如果使用Immutable.js),您可以改为使用#0,不要将splice()'p'混淆。

const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];

解决方案和性能

今天(2020.04.24),我在macOS v10.13.6(High Sierra)上对Chrome81.0、Safari13.1和Firefox 75.0进行了测试。

结论

对于所有浏览器

  • 令人惊讶的是,对于小型阵列,基于slicereduce(D,E,F)的非就地解决方案通常比就地解决方案快10x-100倍
  • 对于大数组,基于splice(AI、BI和CI)的就地解决方案最快(有时~100倍-但这取决于数组大小)
  • 对于小数组,BI解决方案最慢
  • 对于大型阵列,E解是最慢的

在此处输入图片描述

详情

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

  • 测试包含10个元素的数组-您可以运行它这里
  • 测试包含1,000,000个元素的数组-您可以运行它这里

测试代码显示在下面的代码片段中:

jsfiddle

function AI(arr, i, el) {arr.splice(i, 0, el);return arr;}
function BI(arr, i, el) {Array.prototype.splice.apply(arr, [i, 0, el]);return arr;}
function CI(arr, i, el) {Array.prototype.splice.call(arr, i, 0, el);return arr;}
function D(arr, i, el) {return arr.slice(0, i).concat(el, arr.slice(i));}
function E(arr, i, el) {return [...arr.slice(0, i), el, ...arr.slice(i)]}
function F(arr, i, el) {return arr.reduce((s, a, j)=> (j-i ? s.push(a) : s.push(el, a), s), []);}


// -------------// TEST// -------------
let arr = ["a", "b", "c", "d", "e", "f"];
let log = (n, f) => {let a = f([...arr], 3, "NEW");console.log(`${n}: [${a}]`);};
log('AI', AI);log('BI', BI);log('CI', CI);log('D', D);log('E', E);log('F', F);
This snippet only presents tested code (it not perform tests)

Example results for a small array on Google Chrome are below:

Enter image description here

不可变插入

如果您需要就地插入数组,使用#0方法肯定是最佳答案。

但是,如果您正在寻找一个返回新更新数组而不是在插入时更改原始数组的不可变函数,则可以使用以下函数。

function insert(array, index) {const items = Array.prototype.slice.call(arguments, 2);
return [].concat(array.slice(0, index), items, array.slice(index));}
const list = ['one', 'two', 'three'];
const list1 = insert(list, 0, 'zero'); // Insert single itemconst list2 = insert(list, 3, 'four', 'five', 'six'); // Insert multiple
console.log('Original list: ', list);console.log('Inserted list1: ', list1);console.log('Inserted list2: ', list2);

备注:这是ES6之前的方法,因此它适用于较旧和较新的浏览器。

如果您使用的是ES6,那么您也可以尝试其余参数;请参阅这个答案

我喜欢一点安全,我用这个:

Array.prototype.Insert = function (item, before) {if (!item) return;if (before == null || before < 0 || before > this.length - 1) {this.push(item);return;}this.splice(before, 0, item);}

var t = ["a", "b"]
t.Insert("v", 1)
console.log(t)

这是现代(打字稿功能)方式:

export const insertItemInList = <T>(arr: T[],index: number,newItem: T): T[] => [...arr.slice(0, index), newItem, ...arr.slice(index)]

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

const numbers = ['one', 'two', 'four', 'five']numbers.splice(2, 0, 'three');
console.log(numbers)

阅读更多关于Array.prototype.splice()这里

你可以使用splice()

splice()方法在添加元素时通常会收到三个参数:

  1. 要添加项的数组的索引
  2. 要删除的项目数量,在这种情况下是0
  3. 该元素添加。

let array = ['item 1', 'item 2', 'item 3']let insertAtIndex = 0let itemsToRemove = 0    
array.splice(insertAtIndex, itemsToRemove, 'insert this string on index 0')
console.log(array)

我是这样做的:

const insert = (what, where, index) =>([...where.slice(0, index), what , ...where.slice(index, where.length)]);

const insert = (what, where, index) =>([...where.slice(0, index), what , ...where.slice(index, where.length)]);  
const list = [1, 2, 3, 4, 5, 6];const newList = insert('a', list, 2);
console.log(newList.indexOf('a') === 2);

这是一个支持同时插入多个值的简单函数:

function add_items_to_array_at_position(array, index, new_items){return [...array.slice(0, index), ...new_items, ...array.slice(index)];}

使用示例:

let old_array = [1,2,5];
let new_array = add_items_to_array_at_position(old_array, 2, [3,4]);
console.log(new_array);
//Output: [1,2,3,4,5]
var array= [10,20,30,40]
var i;
var pos=2; //pos=index + 1/*pos is position which we want to insert at which is index + 1.position two in an array is index 1.*/
var value=5//value to insert
//Initialize from last array element
for(i=array.length-1;i>=pos-1;i--){
array[i+1]=array[i]
}
array[pos-1]=value
console.log(array)

你可以用array.splice:

/*** @param arr:  Array* @param item:  item to insert* @param index: index at which to insert* @returns array with the inserted element*/export function _arrayInsertAt<T>(arr: T[], item: T, index: number) {return  arr.splice(index, 0, item);;}

文档的array.slice