【Javascript】 配列

Javascriptにおける配列は、単なる配列を保存するだけでなく、mapやfilterなど、便利なメソッドが揃っています。

配列の作り方

const a = [1, 2, 3]
const b = [1, [20, 30], [100, 200, 300]] // 最大2次元の配列

[]で囲み、その中に要素をカンマ区切りで入れることで、配列を作っています。

配列の値を利用する方法は他言語と同じです。

件数の取得

.lengthを用います。

const a = [1, 2, 3];
for (let i = 0; i < a.length; i++) {
    // ...
}

代入

配列の代入では、参照が代入されます。

const a = [3, 5, 1, 9, 3];
const b = a; // 配列本体はコピーされず, 参照の値が代入される
b[3] = 100;
console.log(a);
console.log(b);
[ 3, 5, 1, 100, 3 ]
[ 3, 5, 1, 100, 3 ]

1段階目までのコピーはスプレッド構文を、それ以上のディープコピーはいくつか方法があります。(後述)

配列の操作

末尾に要素の追加(push)

末尾に追加するには、pushを使います。

const a = [1, 2, 3];
a.push(100);
console.log(a);
[ 1, 2, 3, 100 ]

末尾の要素の削除(pop)

末尾の要素の削除は、popを使います。

popすると同時に、その削除した値が戻り値として返されます。

const a = [1, 2, 3];
const v = a.pop();
console.log(v);
console.log(a);
3
[ 1, 2 ]

要素の挿入と削除(splice)

spliceを用います。このメソッドは、追加と削除両方の操作が可能です。

pushpopでは対応できない場合に用います。

splice(場所指定, 消す数, 追加する要素)です。要素の追加では、指定したインデックスの直前に追加されます。

追加

削除する数を0とすれば、追加のみが可能です。

const x = [1, 2, 3];
x.splice(2, 0, 100);
console.log(x);
[ 1, 2, 100, 3 ]

この場合、2番目のインデックスの直前に100を追加します。

削除

削除する数を設定します。ここで、追加する要素の引数には何も与えないようにします。

const x = [1, 2, 3];
x.splice(1, 1);
console.log(x);
[ 1, 3 ]

この場合、1番目のインデックスを始点として、1個削除しています。

連結(concat)

concatで連結します。

const a = [1, 2, 3];
const b = [4, 5, 6];
console.log(a.concat(b));
[ 1, 2, 3, 4, 5, 6 ]

引数に入れた配列が後ろに連結されます。

連結(スプレッド構文)

スプレッド構文でも同様に連結できます。

スプレッド構文はこのあとのセクションにあります。

const a = [1, 2, 3];
const b = [4, 5, 6];
console.log([...a, ...b]);
[ 1, 2, 3, 4, 5, 6 ]

もちろん、b = [...a, 4, 5, 6];のようにも連結できます。

ソート(sort)

sortを利用します。

const a = [3, 5, 1, 9, 3];
a.sort();
console.log(a);
[ 1, 3, 3, 5, 9 ]

中に連想配列を保つ場合、第2引数に、どのように比較するかを関数で指定します。

let a = [
    {i: 5},
    {i: 10},
    {i: 1},
    {i: 9},
]
a.sort((lhs, rhs) => {
    return lhs.i - rhs.i; // 正負を入れ替えれば降順になる
});
console.log(a);
[ { i: 1 }, { i: 5 }, { i: 9 }, { i: 10 } ]

sortの第1引数に、比較用の関数を与えます。要素を比較するとき、左辺<右辺なら負数、左辺==右辺なら0、左辺>右辺なら正数を返すと昇順ソートになります。

比較用関数には引数が2つあり、これは比較しようとしている配列の要素です。

lhsはLeft-hand sideの頭文字を取ったもので、左辺という意味です。rhsも同様にRight-hand sideの頭文字で、右辺の意味です。

非破壊なソート

上のソートでは、元の配列が変化してしまします。そこで、1段目をコピーすることでその破壊を防ぎます。

const a = [3, 5, 1, 9, 3];
const b = [...a].sort();
console.log(a);
console.log(b);
[ 3, 5, 1, 9, 3 ]
[ 1, 3, 3, 5, 9 ]

スプレッド構文

Javascriptの配列を一旦解体するには、スプレッド構文を用います。

let a = [1, 2, 3];
let b = [100, 200, ...a];

console.log(b);
[100, 200, 1, 2, 3]
function hoge(a, b, c) {
    return a + b + c;
}

let a = [1, 2, 3]
console.log(hoge(...a));
6

スプレッド構文は、解体した配列の行き先が存在している必要があるのと、次のような使えそうで使えない場面があります。

const a = [1, 2, 3];
const h, i, j = ...a; // Uncaught SyntaxError: Unexpected token '...'

しかし、配列の連結、実引数への変形など、使えれば非常に簡潔に書くことができます。

ディープコピー

1段階目だけなら、スプレッド構文で簡単にコピーできます。しかし、それより深いなら別の方法になります。

let a = [1, 2, 3, [4, 5, 6]];
let b = [...a]; // スプレッド構文

b[2] = 40;
b[3][0] = 100;

console.log(a);
console.log(b);
[1, 2, 3, [100, 5, 6]]
[1, 2, 40, [100, 5, 6]]

...aでは、aの値を展開するという動作をします。つまり、[1, 2, 3]だったものは実質1, 2, 3になります。

ライブラリを用いる

例えば、lodashなどを用います。

仮に自前で実装するとすれば、DFSなどを用いることになると思います。

const _ = require('lodash');

const a = [
    1,
    2,
    [11, 12],
    [
        21, 22,
        [231, 232, 233],
    ]
];

const b = _.cloneDeep(a);

b[1] = 100;
b[2][0] = 4500;
b[3][2][1] = 1000;

console.log(a);
console.log(b);
[ 1, 2, [ 11, 12 ], [ 21, 22, [ 231, 232, 233 ] ] ]
[ 1, 100, [ 4500, 12 ], [ 21, 22, [ 231, 1000, 233 ] ] ]

深い階層までしっかりコピーされていることがわかります。

走査する方法

Javascriptでは、単純なfor (let i = 0; ...) {}だけでなく、すべての要素を見るいくつかの方法があります。

詳しくは下のページにまとめてあります。

まとめ

配列の操作でよく利用するメソッドを紹介しました。とくにpushは非常に利用頻度が高いです。

配列操作はどの言語でも割と似ているので、比較的すぐに覚えることができるのではないでしょうか。

jsの配列

役に立ったらシェアしよう!