配列を別の配列内に挿入するより効率的な方法は何ですか。
a1 = [1,2,3,4,5];
a2 = [21,22];
newArray - a1.insertAt(2,a2) -> [1,2, 21,22, 3,4,5];
a2配列が大きい場合、spliceを使用して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 +では、spread演算子を代わりに使用して、これを少し良くすることができます
a1.splice(2, 0, ...a2);
apply
を保持している場合、Chromeではstackoverflow例外がスローされます。jsfiddle.net/DcHCYまた、私はFFとIEを信じているjsPerfでも発生します。しきい値は約500kです
target.slice(0, insertIndex).concat(insertArr, target.slice(insertIndex));
jsperf.com / inserting
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
最初は間違っていた。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)
[docs]を使用しての最初の2つの要素を返しますa1
(0
は開始インデックスで2
、要素はdeleteCountですa1
が、変更されていません)。
中間結果:[1,2]
次に、concat(a2)
[docs]を使用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 );
この質問に対する真に創造的な答えがいくつかあります。これは、配列から始めたばかりの人のための簡単な解決策です。必要に応じて、ECMAScript 3準拠のブラウザーまで機能するように設定できます。
始める前に、スプライスについて知っておいてください。
Mozilla開発者ネットワーク:Array.prototype.splice()
まず、の2つの重要な形式を理解し.splice()
ます。
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()
と、目的は分割することですa1
上記の2つの形式のいずれかを使用して、ヘッド配列とテール配列する。
メソッド#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)またはのvar
代わりに使用するだけでECMAScript 3および5で動作しますlet
const
ます。
** 7)提示されている他の多くのソリューションとは異なり、体に平手打ちする頭と尾があることを保証します。境界の前または後に配列を追加する場合は、少なくとも以下を使用する必要があります.concat()
!!!!
注:スプレッドオペアレーター...
を使用すると、これらすべてを簡単に実行できます。
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
}
a2
配列も変更されますが、これはおそらく非常に望ましくありません。また、あなたがに行く必要はありませんArray.prototype
あなたはすぐそこにスライス機能を持っている場合a1
かa2
。
apply()
。
Array.prototype.splice
対a1.splice
:)
.concat
新しい配列を返しますsplice
。既存の配列を変更することはありません。する必要がありますargs = args.concat(arrayToInsert);
ここに特別なトリックのない私のバージョンがあります:
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;
}
.apply()
。
あなたは新しいものを作成せずに配列に別の配列を挿入したい場合は、最も簡単な方法は、どちらかを使用することである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
が可変数の引数を取るため、機能します。おまけで、アレイを取り付ける端を簡単に選択できます!
a1.concat(a2)
またはa2.concat(a1)
私はあなたが提案したものよりも簡単なものを考案しました。ただし、問題は配列の境界の間に配列を挿入することであり、配列を最初または最後に排他的に追加するのではありません。;-)
別のスレッドで述べたように、上記の答えは非常に大きな配列(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]);
}
}
}