配列(リスト)のデータ型の各プログラミング言語別の概要

同じ型のオブジェクトを並べたもので、配列、リストなど、言語によって呼び方は違う。型が違うオブジェクトが混ざっていてもよい言語もある。

C言語 / C++

配列の仕組みがある。配列のメモリ領域を確保した時点で大きさを変更できないので、固定長配列になる。ただ、大きさは型の一部ではないので、要素の型が同じであれば大きさが異なる2つの配列も同じ型になる。

インデックスは0から始まる。

変数宣言のときに配列を書くには

int arr[] = {1, 2, 3};

配列の変数は配列の先頭を指すポインタのように振る舞う。

Go言語 (golang)

配列の仕組みとスライスというのがある。

配列(Array)

配列の型は大きさと要素の型で表す。他の言語の配列と違って大きさも型の一部であり、大きさの異なる配列は型が違いう扱いになる。

Go言語の配列はC言語の配列と違って、配列の先頭のポインタというわけではなく、配列の大きさの情報も含めた配列全体を表す。

配列生成の例

arr := [...]string{"abc", "def", "ghi"}

var arr = [...]string{"abc", "def", "ghi"}

var arr [3]string = [...]string{"abc", "def", "ghi"}

以下のように初期化しないとすべての要素がゼロ値の配列になる。ゼロ値は、数値は0または0.0bool型はfalse、文字列は空文字列("")、ポインタやスライスなどはnilである。

var arr [3]string

スライス(Slice)

スライス生成の例

sl := []string{"abc", "def", "ghi"}

var sl = []string{"abc", "def", "ghi"}

var sl []string = []string{"abc", "def", "ghi"}

以下の生成方法では、配列と同じく要素がゼロ値で初期化される。

sl := make([]int, size)

var sl = make([]int, size)

var sl []int = make([]int, size)

makeは組み込み関数で、1つ目の引数には型を渡す。このようにGo言語の組み込み関数の中には引数に型を受け取るものがある。

以下のようにスライス自体を初期化しないと nil になる。

var sl []string
// sl == nil

Java

言語の組み込み型である配列と、クラスライブラリでサポートされている java.util.List インターフェースなどのコレクションがある。配列はC言語のと似ていて、生成する時点で長さを指定しなければならず、固定長配列になる。

配列も java.util.List もインデックスは0から始まる。

配列は、プリミティブ型や参照型(オブジェクト、配列)を要素として持つことができる。 java.util.List などのコレクションは、プリミティブ型を要素として持つことができず、参照型(オブジェクト、配列)のみである。

配列

配列生成は

int[] arr = {1, 2, 3};

または

int[] arr = new int[]{1, 2, 3};

のように書けばできる。

要素の値を指定して初期化する必要がない場合は、

int[] arr = new int[1024];

でもよい。この場合、要素は全部0になる。intなどの数値型であれば全部0booleanであればfalse、参照型(オブジェクト、配列)であればnullになる。 Integerの配列であれば0ではなくnullになる。

配列を java.util.List に変換するには相互変換参照。

java.util.List

インスタンス生成の例

import java.util.List;
import java.util.ArrayList;

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");

java.util.List を配列に変換するには相互変換参照。

Scala

Scalaのコレクションフレームワークとして scala.collection.Seq トレイトや、関連する多くのトレイト、実装クラスがある。

Javaの組み込み型である配列と、Javaのクラスライブラリでサポートされている java.util.List インターフェースやその実装クラスも使えるが、 Javaのライブラリとのやりとりで限定的に使うことが多い。 Scalaのコレクションフレームワークのほうが使いやすいためである。

Scalaのコレクションフレームワークにある基本的なトレイトだけでもたくさんあり、以下のページにある図がわかりやすい。

Scalaでは、コレクションはJavaでいうプリミティブ型も要素として持つことができる。たぶんJVM上では対応するラッパークラスにボクシングされているのだとは思う。

scala.collection.immutable.List は不変型の片方向連結リストを実装した scala.collection.Seq のサブクラスで、Scalaでは非常によく使われる。片方向連結リストなので、先頭から順番にアクセスしたり、先頭付近を変更するには速いが、インデックスでのランダムアクセスは遅い。不変(イミュータブル)なので、変更するには変更後の新しいインスタンスを生成することになる。インスタンス自体を変更するには可変型の scala.collection.mutable.ListBuffer を使うとよい。 scala.collection.immutable.List は特にインポートしなくても List だけで参照できる。

その他にもたくさんのシーケンシャルなコレクション型がある。

Javaの配列は、Scalaでは scala.Array というクラスのインスタンスということになっていて、いくつかのメソッドが存在するが、JVM上での実体はJavaの配列のままになっている。

Javaの配列も JavaやScalaのクラスライブラリにあるコレクション型もすべて、インデックスは0から始まる。

インスタンス生成の例

// scala.collection.immutable.List
val lst = 1 :: 2 :: 3 :: Nil;
// または
val lst = List(1, 2, 3);

Javaの配列の生成の例

// scala.Array (Javaの配列)
val arr = Array(1, 2, 3);

// 要素を指定せずにサイズだけ指定
val arr = new Array(3);

scala.collection.immutable.List のインスタンス生成の例

list = List(1, 2, 3);
list = 1 :: 2 :: 3 :: Nil;
list = Nil; // 空のList

1行目の List は2行目のように二重コロン :: で区切って書くことも可能。 :: で区切って書く場合は最後が Nil かもしくはなんらかの List であることが必要。

これらのインスタンス生成の例は以下の3行と同じ意味。

arr = scala.Array.apply(1, 2, 3);
list = scala.collection.immutable.List.apply(1, 2, 3);
list = scala.collection.immutable.List.apply(1, 2, 3);
list = scala.collection.immutable.List.apply();

Groovy

def lst = [1, 2, 3]; // java.util.ArrayList

PHP

組み込み型の連想配列のキーに整数を使えば、配列として使うことができる。-> 連想配列

配列を生成する例

$arr = array(1, 2, 3);

最後に余計なカンマがあっても問題ない。

$arr = array(
             1,
             2,
             3,
            );

PHP5.4以降では以下のようにも書ける。

$arr = [1, 2, 3];

上記のように書けばインデックスは0から始まるが、中身は単なる連想配列であるので、以下のようにインデックスは順番に並んでいる必要がない。

$arr = array();
$arr[1] = 10;
$arr[3] = 30;

var_export($arr);
// => array (
//      1 => 10,
//      3 => 30,
//    )

要素への代入はまだその変数が存在していなくてもできるみたいで、個人的には非常に気持ち悪い。

// $a はまだ存在していない状況で
// 勝手に $a という配列が存在しているものとして、
// 要素に代入できる。
$a["a"] = 1;
$a["b"] = 1;

var_export($a);
// => array (
//      'a' => 1,
//      'b' => 1,
//    )

要素を参照するには [] を使う。

インデックスは通常は0から始まる。

連想配列のキーは整数と文字列の区別がないので、以下のように、配列に対して数字の文字列でもアクセスできてしまう。

$arr = array();
$arr['1'] = 10;
$arr[3] = 30;

var_export($arr[1]);
// => 10

var_export($arr['3']);
// => 30

var_export($arr);
// => array (
//      1 => 10,
//      3 => 30,
//    )

配列 | PHP Manual
http://php.net/manual/ja/language.types.array.php

配列関係の関数 | PHP Manual
http://php.net/manual/ja/book.array.php

Python

リストおよびタプルというデータ型がある。また、NumPyを導入すればベクトルや行列の計算の得意な固定長の多次元配列を使える。

インデックスは0から始まる。

リストは連結リストではなく可変長配列として実装されている。 NumPyの配列は固定長配列である。

リストとよく似たものでタプルというデータ型もあるが、単なるイミュータブル(要素の書き換えが不能な)なリストという感じで、 Scalaなどのタプルとはだいぶイメージが違う気がする。

Pythonのタプルはイミュータブルなので、 ディクショナリのキーにできる。

リスト、タプルに文字列も含めたものをシーケンス型といわれ、共通の操作がいくつかある。

リスト・タプルの書き方の例

# リスト
lst = [1, 2, 3]

# タプル
tpl = (1, 2, 3)

# 要素が1つのタプル
tpl = (1,)

# リストの内包表記
lst = [i * 2 for i in range(3)] # [0, 2, 4]

タプルは、式の優先順位をコントロールするための () と混同する可能性がなければ、 () を省略し , だけでも表せる。

# タプル
tpl = 1, 2, 3

NumPyの配列の書き方の例

import numpy as np

np.array([1, 2, 3])

Ruby

Arrayという可変長配列のクラスが存在する。要素は異なる型のオブジェクトが混ざっていてもよい。

インデックスは0から始まる。

配列を書くには [] で要素を羅列する。

arr = [1, 2, 3]

要素が文字列の場合は以下のような書き方もできる。

arr = %w(abc def ghi) # ['abc', 'def', 'ghi'] と同じ

この %w の記法を使うと、カッコは比較的なんでもよくて、以下はすべて同じ意味になる。

['abc', 'def', 'ghi']
%w(abc def ghi)
%w[abc def ghi]
%w!abc def ghi!
%w/abc def ghi/

%w の記法では要素間はスペースで区切って、コンマで区切ることはできない。コンマを書いてしまうとそのコンマ辞退も文字列の一部とみなされてしまう。

%w の中では # によるコメントアウトが効かないので以下のようになってしまう。

  p %w(
       aaa
       # bbb
       )
  # => ["aaa", "#", "bbb"]
  p [
       'aaa',
       # 'bbb',
    ]
  # => ["aaa"]

%w の代わりに %W を使うと式展開を使うことができる。

%w と似たような仕組みは文字列(%q)にもある。

nilで埋められた指定サイズの配列を作成するには以下のようにする。

Array.new(10) # nilが10個の配列

Array | Ruby 2.1 リファレンスマニュアル
http://doc.ruby-lang.org/ja/2.1.0/class/Array.html

Perl

Perlにも配列の仕組みがある。配列の要素にはスカラ(文字列、数字、レファレンスなど)しか含められない。

2次元配列のようなものはなく、配列の配列を作ることもできないので、配列へのレファレンスを要素とした配列とする必要がある。

Perlは、リストという用語は配列とは厳密には異なる意味を持ち、 (..., ..., ...) のようなソースコード上の表現をリストといい、それを配列の変数に代入すると配列になり、リストをハッシュの変数に代入するとハッシュ)になる。

配列そのものは変数名が @ で始まり、要素を参照したり要素に代入したりするには @ の代わりに $ で始める。

my @arr = ('abc', 'def', 'ghi');

('abc', 'def', 'ghi') の表記がリストで、@arr が配列になる。

最後に余計なカンマがあっても問題ない。

my @arr = (
           'abc',
           'def',
           'ghi',
          );

以下のような書き方もできる。これは上記例と同じ文字列の配列となる。

my @arr = qw(abc def ghi);

この qw の記法を使うと、カッコは比較的なんでもよくて、以下はすべて同じ意味になる。

('abc', 'def', 'ghi')
qw(abc def ghi)
qw[abc def ghi]
qw{abc def ghi}
qw<abc def ghi>
qw!abc def ghi!
qw/abc def ghi/

qw の記法では要素間はスペースで区切って、コンマで区切ることはできない。コンマを書いてしまうとそのコンマ辞退も文字列の一部とみなされてしまう。コンマで区切ろうとすると、親切にも Possible attempt to separate words with commas という警告が表示されるかもしれない。

qw の中では # によるコメントアウトが効かないので以下のようになってしまう。

my @arr = qw(abc # def ghi);
print "@arr";
# => abc # def ghi

上記のようにコメントアウトをしようとすると、親切にも Possible attempt to put comments in qw() という警告が表示されるかもしれない。

qw と似たような仕組みは文字列にもある。

スカラ1つを配列の変数に代入しようとすると、要素が1つだけの配列になる。

リストはネストすることはできず、ネストして書いたつもりでも平坦になってしまう。

my @arr = (1, 2, (3, 4));
print $arr[2]; # => 3
print $arr[3]; # => 4
my @arr2 = (10, 11, @arr);
print "@arr2"; # => 10 11 1 2 3 4

配列 @var とスカラ変数 $var は名前の衝突をせず共存できるのだが、コードがわかりづらくなるので普通はそんなことはしない。

要素を参照したり代入するときのインデックスは0から始まり、[] を使う。 -> インデックスで要素を参照するには

配列へのレファレンス

[] を使うと、配列へのレファレンスを直接書くことができる。

my $arr = [1, 2, 3];

で、これは以下と同じ。

my @a = (1, 2, 3);
my $arr = \@a;

レファレンスの実体を取り出すには、

@$arr;

[] の中はリストと同じ記法で、リストを入れ子にできないという事情は同じ。レファレンスを含めることはできるので、ネストしたい場合は要素をレファレンスにする。

my @arr = (1, 2, 3);
my $arr2 = [@arr, 4];
my $arr3 = [\@arr, 4];

print Dumper($arr2);
# =>
# $VAR1 = [
#           1,
#           2,
#           3,
#           4
#     ];

print Dumper($arr3);
# =>
# $VAR1 = [
#           [
#             1,
#             2,
#             3
#           ],
#           4
#     ];

ちなみにリストのレファレンスを取ろうとして、[$a, $b, $c] の代わりに \($a, $b, $c) と書いてしまうと、これは実は (\$a, \$b, \$c) と同じ意味になってしまう。

JavaScript

JavaScriptの配列は、キーとして数値を使ったオブジェクトにすぎない。

prototypeArray.prototype が指定され、配列のように振舞う。

下の3つは全部同じ配列を生成する。

var arr = [1, 2, 3];
var arr = {0: 1, 1: 2, 2: 3}; arr.__proto__ = Array.prototype;
var arr = {'0': 1, '1': 2, '2': 3}; arr.__proto__ = Array.prototype;

最後に余計なカンマがあっても本当は問題ないのだが、 IEだとエラーになってしまってだめなので、最後のカンマは付けないほうがよい。最近のIEのバージョンだとどうなのかは知らない。(2013/10/25)

JavaScript の配列と連想配列の違い
http://d.hatena.ne.jp/amachang/20070202/1170386546

インデックスは0から始まる。

CoffeeScript

基本はJavaScriptと同じ。

インデックスは0から始まる。

配列の書き方の例

arr = [1, 2, 3]
arr = [1, 2, 3, ]
arr = [
    1
    2
    3
]

最後に余計なカンマがあっても問題ない。改行すればカンマを省略できる点はJavaScriptにない特徴で便利かもしれない。

このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。