如何在特定索引(JavaScript)的数组中插入项目?

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

arr.insert(index, item)

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

答案

您想要的是本机数组对象上的splice函数。

arr.splice(index, 0, item);将在指定索引处将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());
arr.splice(2, 0, "Lene");
console.log(arr.join());

您可以通过执行以下Array.insert来实现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' ]

除了拼接以外,您可以使用这种方法,该方法不会突变原始数组,但是会使用添加的项创建一个新数组。通常应尽可能避免突变。我在这里使用 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 item
  newItem,
  // 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]

自定义数组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;
};

它可以插入多个元素(就像本地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/

如果您想一次将多个元素插入到数组中,请查看此 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.prototype.insert()的发明必不可少。如果拼接返回了变异数组而不是完全没有意义的空数组,则实际上拼接可能是完美的。所以就这样

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

我建议在这种情况下使用纯JavaScriptJavaScript中也没有 insert 方法,但是我们有一个内置的 Array方法,它可以为您完成工作,称为splice ...。

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

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

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

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

我们可以这样删除3

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

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

[1, 2, 4, 5]

到目前为止,一切都很好,但是如何使用拼接将新元素添加到数组中呢?让我们把 3 放回去...

arr.splice(2, 0, 3);

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

我们再次使用了splice ,但是这次我们为第二个参数传递了0 ,这意味着我们不希望删除任何项目,但是与此同时,我们添加了第三个参数 3,它将在第二个索引处添加。

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

arr.splice(2, 2, 3);

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

[1, 2, 3, 5];

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

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

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

//Append at 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 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

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

var arr = ["apple", "orange", "raspberry"],
    arr2 = [1, 2, 4];

function insert(arr, item, index) {
    arr = arr.reduce(function(s, a, i) {
      i == index ? s.push(item, a) : s.push(a);
      return s;
    }, []);   
    console.log(arr);
}

insert(arr, "banana", 1);
insert(arr2, 3, 2);

即使已经回答了这个问题,我仍在添加此注释,以供选择。

我想将已知数量的项目放置到数组中的特定位置,因为它们来自 “关联数组”(即对象),而根据定义,这些 “数组” 不能保证按排序的顺序排列。我希望结果数组是对象数组,但是对象要按数组中的特定顺序排列,因为数组可以保证它们的顺序。所以我做到了。

首先是源对象,即从 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);