別の配列内に配列を挿入するより効率的な方法は何ですか。
a1 = [1,2,3,4,5];
a2 = [21,22];
newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];
スプライスを使用したa2の反復は、a2配列が大きい場合、パフォーマンスの観点からは少しひどく見えます。
ありがとう。
splice
をいくつかのapply
トリックと組み合わせて使用できます。
a1 = [1,2,3,4,5];
a2 = [21,22];
a1.splice.apply(a1, [2, 0].concat(a2));
console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
ES2015 +では、代わりにスプレッド演算子を使用して、これを少し良くすることができます
a1.splice(2, 0, ...a2);
最初は間違っていました。代わりにconcat()
を使用する必要がありました。
var a1 = [1,2,3,4,5],
a2 = [21,22],
startIndex = 0,
insertionIndex = 2,
result;
result = a1.slice(startIndex, insertionIndex).concat(a2).concat(a1.slice(insertionIndex));
例:http://jsfiddle.net/f3cae/1/
この式は slice(0, 2)
を使用します[ドキュメント]a1
の最初の2つの要素を返します(0
は開始インデックス、2
は要素deleteCountですが、a1
は変更されません)。
中間結果:[1,2]
次に、 concat(a2)
を使用します[ドキュメント]a2
の末尾に[1,2]
を追加します。
中間結果:[1,2,21,22]
。
次に、a1.slice(2)
が、この式の末尾の末尾の.concat()
内で呼び出されます。これは[1,2,21,22].concat(a1.slice(2))
になります。
正の整数引数を持つslice(2)
の呼び出しは、自然数でカウントして2番目の要素の後のすべての要素を返します(5つの要素があるため、[3,4,5]
はa1
から返されます)。別の言い方をすると、特異な整数のインデックス引数は、a1.slice()
に配列のどの位置から要素を返し始めるかを指示します(インデックス2は3番目の要素です)。
中間結果:[1,2,21,22].concat([3,4,5])
最後に、2番目の.concat()
は[3,4,5]
を[1,2,21,22]
の最後に追加します。
結果:[1,2,21,22,3,4,5]
Array.prototype
を変更したくなるかもしれませんが、プロトタイプの継承を使用してArrayオブジェクトを単純に拡張し、その新しいオブジェクトをプロジェクトに注入できます。
しかし、エッジに住んでいる人のために...
例:http://jsfiddle.net/f3cae/2/
Array.prototype.injectArray = function( idx, arr ) {
return this.slice( 0, idx ).concat( arr ).concat( this.slice( idx ) );
};
var a1 = [1,2,3,4,5];
var a2 = [21,22];
var result = a1.injectArray( 2, a2 );
ES2015以降を使用している場合、これを行うことができます。
var a1 = [1,2,3,4,5];
var a2 = [21,22];
a1.splice(2, 0, ...a2);
console.log(a1) // => [1,2,21,22,3,4,5]
スプレッド(...)演算子については、こちらを参照してください https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
spread 演算子を使用すると、複数の引数(関数呼び出しの場合)または複数の要素(配列リテラルの場合)が予想される場所で式を展開できます。
a2 = [21,22];
a1 = [1,2,...a2,3,4,5];//...a2 is use of spread operator
console.log(a1);
私はsplice()
でこれを行う方法を見つけたいと思っていました。繰り返しはしません: http://jsfiddle.net/jfriend00/W9n27/ 。
a1 = [1,2,3,4,5];
a2 = [21,22];
a2.unshift(2, 0); // put first two params to splice onto front of array
a1.splice.apply(a1, a2); // pass array as arguments parameter to splice
console.log(a1); // [1, 2, 21, 22, 3, 4, 5];
汎用関数形式では:
function arrayInsertAt(destArray, pos, arrayToInsert) {
var args = [];
args.Push(pos); // where to insert
args.Push(0); // nothing to remove
args = args.concat(arrayToInsert); // add on array to insert
destArray.splice.apply(destArray, args); // splice it in
}
この質問に対する真に独創的な答えがここにあります。配列から始めたばかりの人向けの簡単なソリューションを次に示します。必要に応じて、ECMAScript 3準拠のブラウザーまでずっと機能するようにできます。
始める前にスプライスについて何かを知ってください。
Mozilla Developer Network:Array.prototype.splice()
まず、.splice()
の2つの重要な形式を理解します。
_let a1 = [1,2,3,4],
a2 = [1,2];
_
方法1)目的のインデックスから開始して、x(deleteCount)要素を削除します。
_let startIndex = 0,
deleteCount = 2;
a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
_
方法2)配列の末尾までの開始インデックスの後の要素を削除します。
_a1.splice(2); // returns [3,4], a1 would be [1,2]
_
.splice()
を使用すると、上記の2つの形式のいずれかを使用して、_a1
_を先頭配列と末尾配列に分割できます。
メソッド#1を使用すると、戻り値が先頭になり、_a1
_が末尾になります。
_let head = a1.splice(startIndex, deleteCount); // returns [1,2], a1 would be [3,4]
_
さて、一気に頭、体(_a2
_)、および尾を連結します
_[].concat(head, a2, a1);
_
したがって、このソリューションは、これまでに紹介した他のどのソリューションよりも現実の世界に似ています。これは、レゴで何をするかではありませんか? ;-)以下は、メソッド#2を使用して実行される関数です。
_/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
let tail = target.splice(startIndex); // target is now [1,2] and the head
return [].concat(target, body, tail);
}
let newArray = insertArray([1, 2, 3, 4], ["a", "b"], 2); // [1, 2, "a", "b", 3, 4]
_
短い:
_/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*/
function insertArray(target, body, startIndex)
{
return [].concat(target, body, target.splice(startIndex));
}
_
より安全:
_/**
*@param target Array The array to be split up into a head and tail.
*@param body Array The array to be inserted between the head and tail.
*@param startIndex Integer Where to split the target array.
*@throws Error The value for startIndex must fall between the first and last index, exclusive.
*/
function insertArray(target, body, startIndex)
{
const ARRAY_START = 0,
ARRAY_END = target.length - 1,
ARRAY_NEG_END = -1,
START_INDEX_MAGNITUDE = Math.abs(startIndex);
if (startIndex === ARRAY_START) {
throw new Error("The value for startIndex cannot be zero (0).");
}
if (startIndex === ARRAY_END || startIndex === ARRAY_NEG_END) {
throw new Error("The startIndex cannot be equal to the last index in target, or -1.");
}
if (START_INDEX_MAGNITUDE >= ARRAY_END) {
throw new Error("The absolute value of startIndex must be less than the last index.");
}
return [].concat(target, body, target.splice(startIndex));
}
_
このソリューションの利点は次のとおりです。
1)単純な前提がソリューションを支配します-空の配列を埋めます。
2)頭、体、尾の命名法は自然に感じる。
3).slice()
への二重呼び出しはありません。まったくスライスしません。
4).apply()
はありません。非常に不必要です。
5)メソッドの連鎖は回避されます。
6)ECMAScript 3および5では、var
またはlet
の代わりにconst
を使用するだけで機能します。
** 7)提示されている他の多くのソリューションとは異なり、身体に平手打ちする頭と尾があることを保証します。境界の前または後に配列を追加する場合、少なくとも.concat()
!!!!を使用する必要があります。
注:スプレッドオペレーター_...
_を使用すると、これをすべて簡単に実行できます。
別のスレッドで述べたように、上記の答えは非常に大きな配列(200K要素)では機能しません。スプライスと手動プッシュに関する別の回答を参照してください: https://stackoverflow.com/a/41465578/1038326
Array.prototype.spliceArray = function(index, insertedArray) {
var postArray = this.splice(index);
inPlacePush(this, insertedArray);
inPlacePush(this, postArray);
function inPlacePush(targetArray, pushedArray) {
// Not using forEach for browser compatability
var pushedArrayLength = pushedArray.length;
for (var index = 0; index < pushedArrayLength; index++) {
targetArray.Push(pushedArray[index]);
}
}
}
ここに特別なトリックのない私のバージョンがあります:
function insert_array(original_array, new_values, insert_index) {
for (var i=0; i<new_values.length; i++) {
original_array.splice((insert_index + i), 0, new_values[i]);
}
return original_array;
}
var a1 = [1,2,3,4,5];
var a2 = [21,22];
function injectAt(d, a1, a2) {
for(var i=a1.length-1; i>=d; i--) {
a1[i + a2.length] = a1[i];
}
for(var i=0; i<a2.length; i++) {
a1[i+d] = a2[i];
}
}
injectAt(2, a1, a2);
alert(a1);
新しい配列を作成せずに配列に別の配列を挿入する場合、最も簡単な方法は、Push
またはunshift
をapply
とともに使用することです
例えば:
a1 = [1,2,3,4,5];
a2 = [21,22];
// Insert a1 at beginning of a2
a2.unshift.apply(a2,a1);
// Insert a1 at end of a2
a2.Push.apply(a2,a1);
これは、Push
とunshift
の両方が可変個の引数を取るために機能します。おまけに、アレイを接続する端を簡単に選択できます!