1251

既存の JavaScript 配列を別の配列で拡張する方法、つまり Python のメソッドをエミュレートする方法はないようですextend

私は次のことを達成したい:

>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]

メソッドがあることは知ってa.concat(b)いますが、最初の配列を単純に拡張するのではなく、新しい配列を作成します。aが よりもかなり大きい場合b(つまり、 をコピーしない場合) に効率的に機能するアルゴリズムが必要aです。

注:これは、配列に何かを追加する方法の複製ではありません。-- ここでの目標は、1 つの配列の内容全体を別の配列に追加し、それを「その場で」行うことです。つまり、拡張配列のすべての要素をコピーすることはありません。

4

19 に答える 19

1876

.pushメソッドは複数の引数を取ることができます。スプレッド演算子を使用して、2 番目の配列のすべての要素を引数として に渡すことができ.pushます。

>>> a.push(...b)

お使いのブラウザーが ECMAScript 6 をサポートしていない場合は、.apply代わりに以下を使用できます。

>>> a.push.apply(a, b)

または、より明確だと思われる場合は、次のようにします。

>>> Array.prototype.push.apply(a,b)

配列が長すぎる場合、これらのソリューションはすべてスタック オーバーフロー エラーで失敗することに注意してくださいb(ブラウザによっては、約 100,000 要素で問題が発生します)。
それが十分に短いと保証できない場合bは、他の回答で説明されている標準のループベースの手法を使用する必要があります。

于 2009-09-03T15:27:55.563 に答える
316

2018年更新より良い答えは私の新しいものですa.push(...b)。質問に実際に答えたことはなかったので、これ以上賛成しないでください。しかし、それは2015年の最初のヒットオンGoogleに関するハックでした:)


単純に「JavaScript 配列 拡張」で検索してここにたどり着いた人は、 を非常にうまく使用できますArray.concat

var a = [1, 2, 3];
a = a.concat([5, 4, 3]);

スレッド スターターが望んでいないため、Concat は新しい配列のコピーを返します。しかし、気にしないかもしれません (確かに、ほとんどの用途ではこれで問題ありません)。


また、スプレッド演算子の形式で、これに適した ECMAScript 6 シュガーもいくつかあります。

const a = [1, 2, 3];
const b = [...a, 5, 4, 3];

(コピーもします。)

于 2015-07-20T16:15:17.563 に答える
229

ループベースの手法を使用する必要があります。使用に基づくこのページの他の回答は.apply、大規模な配列では失敗する可能性があります。

かなり簡潔なループベースの実装は次のとおりです。

Array.prototype.extend = function (other_array) {
    /* You should include a test to check whether other_array really is an array */
    other_array.forEach(function(v) {this.push(v)}, this);
}

その後、次のことができます。

var a = [1,2,3];
var b = [5,4,3];
a.extend(b);

DzinX の回答(push.apply を使用) およびその他の.applyベースのメソッドは、追加する配列が大きい場合に失敗します (テストでは、Chrome では約 150,000 エントリ、Firefox では 500,000 エントリを超えることが示されています)。この jsperfでこのエラーが発生していることがわかります。

第2引数に大きな配列を指定して「Function.prototype.apply」を呼び出すと、コールスタックサイズを超えるためエラーが発生します。(MDN には、 Function.prototype.applyを使用してコール スタック サイズを超える危険性に関する注意事項があります。「適用および組み込み関数」というタイトルのセクションを参照してください。)

このページの他の回答との速度比較については、この jsperfをチェックしてください(EaterOfCode に感謝します)。ループベースの実装は、 を使用した場合と同様の速度ですArray.push.applyが、 よりも少し遅くなる傾向がありますArray.slice.apply

興味深いことに、追加する配列がスパースである場合、forEach上記のベースド メソッドはスパース性を利用して、ベースド メソッドよりも優れたパフォーマンスを発揮し.applyます。これを自分でテストしたい場合は、この jsperfをチェックしてください。

ところで、(私がそうであったように!) forEach の実装を次のようにさらに短縮する誘惑に駆られないでください。

Array.prototype.extend = function (array) {
    array.forEach(this.push, this);
}

これはガベージ結果を生成するためです。なんで?は、呼び出す関数に 3 つの引数を提供するためArray.prototype.forEach、これらは (element_value、element_index、source_array) です。forEach「forEach(this.push, this)」を使用すると、これらすべてが反復ごとに最初の配列にプッシュされます。

于 2013-06-28T15:16:22.177 に答える
175

私が最近最もエレガントに感じているのは:

arr1.push(...arr2);

スプレッド演算子に関するMDN の記事では、ES2015 (ES6) でのこの素敵な甘い方法について言及しています。

より良いプッシュ

例: push は、配列を既存の配列の末尾にプッシュするためによく使用されます。ES5 では、これはしばしば次のように行われます。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Append all items from arr2 onto arr1
Array.prototype.push.apply(arr1, arr2);

スプレッドのあるES6では、これは次のようになります。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);

arr2jcdudeの回答によると、コールスタックがオーバーフローするため、巨大にならないことに注意してください(約100 000アイテム未満に保ちます)。

于 2016-02-05T11:27:59.383 に答える
37

jQuery を使いたい場合は$.merge()があります

例:

a = [1, 2];
b = [3, 4, 5];
$.merge(a,b);

結果: a =[1, 2, 3, 4, 5]

于 2013-12-24T15:51:12.790 に答える
19

上記の方法が気に入っていa.push.apply(a, b)ます。必要に応じて、次のようなライブラリ関数をいつでも作成できます。

Array.prototype.append = function(array)
{
    this.push.apply(this, array)
}

そして、このように使用します

a = [1,2]
b = [3,4]

a.append(b)
于 2013-01-07T10:39:00.560 に答える
14

を使用してそれを行うことが可能ですsplice()

b.unshift(b.length)
b.unshift(a.length)
Array.prototype.splice.apply(a,b) 
b.shift() // Restore b
b.shift() // 

しかし、醜いにもかかわらずpush.apply、少なくとも Firefox 3.0 では より速くはありません。

于 2009-09-17T12:51:18.930 に答える