プログラム言語 配列

配列の基底クラス

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

object o = array;
配列を含む全ての型はobjectを継承しているので格納可能

int i = ((int[][])o)[2][1];
// i : 3

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

Object o = array;
配列を含む全ての型はobjectを継承しているので格納可能

int i = ((int[][])o)[2][1];
// i : 3

文字列→配列 / 文字列←配列

string samplestr = "1,2,3,4,5";
string[] ary = samplestr1.Split(new char[] {','});
myAray[1] : "2"

string samplestr = @"aaaa@@bbb,,@@cc dddd,eee f";
string[] ary = samplestr.Split(
 separator: new string[]{ ",", " ", "@@" },
 options: StringSplitOptions.RemoveEmptyEntries);
 
string[] ary = samplestr.Split(
 separator: new string[] { ",", " ", "@@" },
 options: StringSplitOptions.None);
 
文字列でなく、文字で分割する場合 
string[] ary = samplestr.Split(
 separator: new [] { ',', ' ', '@' },
 options: StringSplitOptions.~);

Dim samplestr As String = "1,2,3,4,5"
Dim myAray() As String = samplestr.Split(",")
'myAray(1):2
Dim ReturnValue() As String

' "," を区切りとして分ける
ReturnValue() = Split("文字列1,文字列2,文字列3", ",")

ReturnValue(0) = "文字列1"
ReturnValue(1) = "文字列2"
ReturnValue(2) = "文字列3"

var Text = "A,B,C"
var Elm = Text.split(",");
⇒ Elm[0] : "A"
⇒ Elm[1] : "B"
⇒ Elm[2] : "C"
文字列→配列
$ary = explode(',', 'aaa,bbb,ccc,ddd');
$ary[2]:ccc

配列→文字列
$list = [1, 3, 5];
print( implode('_', $list) );
→1_3_5

$list = [
 '1' => 'A1',
 '3' => 'A3',
 '5' => 'A5',
];
print( implode('_', $list) );
→A1_A3_A5
キーではなく、値が連結される

split
指定の文字列を、指定の文字で分割して配列に格納する

#指定の文字列(分割対象)
my $str= "a/b/c/d/e";

#指定の文字で分割する場合
my @ary = split('/' , $str);

#正規表現リテラルで分割する場合
my @ary = split(/\// , $str);
#「/」を引数で指定する場合は「\」を付ける(エスケープ)
#my @ary = split(/// , $str); はダメ

#指定数のみ要素に分割する。残りは単一の要素
my @ary = split('/' , $str, 3);
⇒ $ary[0] : a
⇒ $ary[1] : b
⇒ $ary[2] : c/d/e

qw演算子
「 (スペース)」で区切られた文字を配列に格納する
my @ary = qw( 1 2 3 );
⇒ @ary = (1,2,3);と同じ
区切り文字(デミリタ)にはどんな文字でも使用可「qw//」、「wq{}」、「qw[]」、「qw<>」他
my @ary = qw/ 1 2 3 /;
my @ary = qw{ 1 2 3 };
my @ary = qw[ 1 2 3 ];
my @ary = qw< 1 2 3 >;

join
※配列を結合する
my @ary = (1,2,3);
my @str = join('-' , @ary);
⇒ @str : 1-2-3

メールアドレスにおいて、ローカルパートとドメイン名を「@」で結合する
(配列でなく第二・第三引数に文字列を渡すやり方も可)
my $local = "aaa";
my $domain = "test.com";
my $adress = join("@" , $local , $domain);
⇒ aaa@test.com

#改行を挟む
my $str = join('\n' , @str);

配列のコピー

clone()
配列から配列へ全要素をコピー
配列同士の要素数は異なっていてもOK

int[] before = new int[]{5,5,5};
int[] after = before.clone();
⇒after {5,5,5}

System.arraycopy()
配列から配列へ指定の要素をコピー
配列同士の要素数は同じ

int[] before = new int[]{5,5,5};
int[] after = new int[3];

//System.arraycopy(src, srcPos, dest, destPos, length)
System.arraycopy(before, 1, after, 1, 2);
before {5,5,5}
index:1から2文字をコピー↓

after {0,0,0}
index:1から2文字へコピー↓

after {0,5,5}

'配列コピー
Dim Before() As Integer
Dim After() As Integer

For elmCnt = 0 To UBound(Before) – 1
  After(elmCnt) = Before(elmCnt)
Next elmCnt

Variant型の配列であれば
After = Before
も可。
しかし遅い。

一次元配列

int[] myInt = {1,2};
myInt[0] = 1;
myInt[1] = 2;
myInt[2] = 3; ⇒エラー

var x1 = myInt.First();
var x2 = myInt.Last();
var x3 = myInt.Min();
var x4 = myInt.Max();
var x5 = myInt.Count();
※配列は各IEnumerable拡張メソッドを使用可能
プログラム言語 LINQ.Enumerable」参照

型推論を用いた配列
var ary = new[] { 1, 2, 3, 4, 5 };

var ary = new[]
{
 new[] { 1,2,3 },
 new[] { 1 },
 new[] { 1,2 }
};

匿名クラスを用いた配列
var ary = new[]
{
 new { x = 1, y = 1 },
 new { x = 2, y = 1 },
 new { x = 3, y = 1 }
};

int myArray1[] = { 1, 2, 3};
// myArray[0]:1
// myArray[1]:2
// myArray[2]:3


// int myArray[3] = { 1, 2, 3, 4 };
// エラー

int myArray2[3] = { 1, 2 };
// myArray[0]:1
// myArray[1]:2
// myArray[2]:0


for each (int var in myArray2)
{
  Console::WriteLine(var);
  // → 1 2 0
};

// 配列全体のバイト数
int size = sizeof(myArray2);
// 12

// 要素のバイト数
int size = sizeof(myArray2[0]);
// 4

// 要素数
int size = sizeof(myArray2) / sizeof(myArray2[0]);
// 3

マクロを使用
wchar_t myChar1[] = L"VisualC++";
wchar_t *myChar2 = L"VisualC#";

int elmCnt;
elmCnt = _countof(myChar1);
→10
終端文字(\0)を含んだ要素数

elmCnt = _countof(myChar2);
コンパイルエラー
配列しか引数に指定できない。

Dim myInt() As Integer = {1, 2}
myInt(0) = 1
myInt(1) = 2
myInt(2) = 3 ⇒エラー

Dim x1 As Integer = myInt.First()
Dim x2 As Integer = myInt.Last()
Dim x3 As Integer = myInt.Max()
Dim x4 As Integer = myInt.Min()
Dim x5 As Integer = myInt.Count()

Dim MyArray(3) As String
Dim MyArray(2 To 5) As String

MyArray(0) = "A"
MyArray(1) = "B"
MyArray(2) = "C"
MyArray(3) = "D" ←エラー

Dim myAry() As Integer
Dim elmCnt As Integer

elmCnt = UBound(myAry)
'実行時エラー

ReDim myAry(0)
elmCnt = UBound(myAry)
elmCnt:0

Dim myAry() As Variant
Dim elmCnt As Integer

myAry() = Array(1, 2, 3, 4, 5)
elmCnt = UBound(myAry)
elmCnt:4

int[] array = new int[3];
array[0] = 5;
array[1] = 5;
array[2] = 5;
array[3] = 5; ⇒ 実行時エラー

int array[] = new int[3]; も可

宣言と同時に要素を設定
int array[] = new int[]{5,5,5};
int array[] = {5,5,5};

//方法①
var strTest = new Array(3);

strTest[0] = 'test1';
strTest[1] = 'test2';
strTest[2] = 'test3';

//方法②
var strTest = new Array('test1', 'test2', 'test3');

要素指定追加
$ary[0] = '1番目要素';
$ary[1] = '2番目要素';
$ary[2] = '3番目要素';

range()関数利用
$ary = array(1, 2, 3);  → 1, 2, 3
$ary = range(1, 5);  → 1, 2, 3, 4, 5
$ary = range(1, 10, 2);  → 1, 3, 5, 7, 9
$ary = range('a', 'f');  → 'a', 'b', 'c', 'd', 'e', 'f'
$ary = array_fill(0, 3, 'foo');  → "foo", "foo", "foo"
$ary = array_pad(array(), 3, 'foo');  → "foo", "foo", "foo"

配列判定
if (is_array($ary)) echo '配列です';

用素数
$cnt = count($ary);

※変数に「@」を付ける。arrayの「a」

@x[0] = 1;
@x[1] = 'aaa';

print "@[1]\n";
⇒aaa

@x = (1, 'two');
@x[2] = '3′;
@x[3..4] = ('four', 'five');

print "@x\n";
print "@x[1..3]\n";
⇒1 two 3 four five
⇒two 3 four

最大Index値、要素数

#」を付ける
my @ary = (1,2,3);
my $cnt = $#ary;
⇒2 (Index値)

何も付けない
my @ary = (1,2,3);
my $cnt = @ary;
⇒3 (要素数)

scalar」を付ける
my @ary = (1,2,3);
my $cnt = scalar @x
⇒3 (要素数)

配列的代入
( $year, $month, $day) = (1978, 8, 4);
print $year\n";
print $month\n";
print $day\n";
⇒1978
⇒8
⇒4

並び替え(自然順序)

自然順序:数字、アルファベット順等

public static void main(String[] args) {
 Integer[] ary1 = {3, 1, 2};
 Arrays.sort(ary1);
 →1 2 3

 Object[] ary2 = { new String("aa"), new Integer(1), "5", 0};
 Arrays.sort(ary2); →実行時エラー
}

ポインターによる配列操作

通常配列
int array[5] = { 1, 2, 3, 4, 5 };
arrayに配列の先頭アドレスを格納

int ret;
ret = array[0];
ret = *array;
ret:1

ret = array[1];
ret = *(array + 1);
ret:2

ret = fnPlus(array, 5);
ret:15
ret = fnPlus(&array[0], 5);
配列の先頭アドレスを渡す
ret:15

メモリ領域の動的確保
ポインタ変数:pに配列の先頭アドレスを格納

int *p = new int[5]{ 1, 2, 3, 4, 5 };

ret = *(p + 1);
ret:2
ret = *(p + 2);
ret:3

ret = fnPlus(p, 5);
ret:15

delete p;

int fnPlus(int *p, int elmCnt)
{
 int sum = 0;
 for (int i = 0; i < elmCnt; i++)
 {
  sum += *(p + i);
 }
 return sum;
}

配列の要素数変更

using System.Collections;

int[] ary = { 1, 2, 3 };
Array.Resize(array: ref ary, newSize: 5);
参照渡しで配列を渡す。(「プログラム言語 変数/値渡し・参照渡し」参照)

ary[3] = 4;
ary[4] = 5;
ary[5] = 6; ⇒ エラー

配列⇒リスト変換
ArrayList list = new ArrayList(ary);

list.Add(value: 6);

リスト⇒配列変換
ary = (int[])list.ToArray(typeof(int));
ary[5] += 1;
ary[5] : 7

ラムダ式を利用した配列の初期化(再配置)については「ラムダ式/配列の初期化」参照

Imports System.Collections

Dim ary() As Integer = {1, 2, 3}

Array.Resize(array:=ary, newSize:=5)

ary(3) = 4
ary(4) = 5
ary(5) = 6 ⇒エラー

‘ 配列⇒リスト変換
Dim list As New ArrayList(ary)

list.Add(6)

‘ リスト⇒配列変換
ary = DirectCast(list.ToArray(GetType(Integer)), Integer())

要素数無しで定義
Dim MyArray() As String
Dim MyArray(3) As String

要素数定義
Redim MyArray(3)
MyArray(0) = "A"
MyArray(1) = "B"
MyArray(2) = "C"
MyArray(3) = "D" ←エラー

既存要素を維持したままで新要素を追加
Redim Preserve MyArray(4)
MyArray(3) = "D" ←OK

Redim MyArray(4)だと全要素が初期化される

要素自動追加
$list[0] = '1番目要素';
$list[] = '2番目要素';
$list[] = '3番目要素';

指定要素削除
unset($list['3']);
unset($list[3]);

$listの末尾に追加
array_push($list, 4);
$list[] = 4 の方が速い

$listの末尾から要素を1つ削除
array_pop($list);

$listの先頭から要素を1つ削除
array_shift($list);

$listの先頭に追加
array_unshift($list, 4);

配列の連結

連結方法 重複時の挙動
+ 第一配列優先
array_merge() 第二配列優先
array_merge_recursive() 両方優先

【「+」による一般配列連結】
$list1 = [1, 3, 5];
Array(
  [0] => 1
  [1] => 3
  [2] => 5
)

$list2 = [1, 2, 3,4];
Array(
  [0] => 1
  [1] => 2
  [2] => 3
  [3] => 4
)

$list3 = $list1 + $list2;
Array(
  [0] => 1
  [1] => 3
  [2] => 5
  [3] => 4
)
第一配列に無い要素が追加追加される

【「+」による連想配列連結】
$list1 = [
 'A1' => 'A1',
 'A3' => 'A3',
 'A5' => 'A5',
];
$list2 = [
 'A1' => 'A1',
 'A2' => 'A2',
 'A3' => 'A3',
];

$list3 = $list1 + $list2;
Array(
  [A1] => A1
  [A3] => A3
  [A5] => A5
  [A2] => A2
)
第一配列に無い要素が追加される

【「array_merge」による通常配列連結】
$list1 = [1, 3, 5];
Array(
  [0] => 1
  [1] => 3
  [2] => 5
)

$list2 = [1, 2, 3,4];
Array(
  [0] => 1
  [1] => 2
  [2] => 3
  [3] => 4
)

$list3 = array_merge($list1, $list2);
Array(
  [0] => 1
  [1] => 3
  [2] => 5
  [3] => 1
  [4] => 2
  [5] => 3
  [6] => 4
)
インデックス番号が重複する場合は後ろに追加される
第一配列に無い要素も追加される

【「array_merge」による連想配列連結】
$list1 = [
 'A1' => 'A1-1',
 'A3' => 'A3-1',
 'A5' => 'A5-1',
];

$list2 = [
 'A1' => 'A1-2',
 'A2' => 'A2-2',
 'A3' => 'A3-2',
];

$list3 = array_merge($list1, $list2);
Array(
  [A1] => A1-2
  [A3] => A3-2
  [A5] => A5-1
  [A2] => A2-2
)
キーが重複する場合は第二配列が優先される
第一配列に無い要素も追加される

【「array_merge_recursive」による連想配列連結】
$list1 = [
 'A1' => 'A1-1',
 'A3' => 'A3-1',
 'A5' => 'A5-1',
];

$list2 = [
 'A1' => 'A1-2',
 'A2' => 'A2-2',
 'A3' => 'A3-2',
];

$list3 = array_merge_recursive($list1, $list2);
Array(
  [A1] => Array
    (
      [0] => A1-1
      [1] => A1-2
    )
  [A3] => Array
    (
      [0] => A3-1
      [1] => A3-2
    )
  [A5] => A5-1
  [A2] => A2-2
)
キーが重複した場合、子配列が生成される

配列の置換

array_splice(操作対象配列, 操作開始位置, 置換要素数, 置換対象配列)

$list = [
 'A',
 'B',
 'C',
];
array_splice($list, 0, 2, ['D1', 'D2', 'D3']);
$listの1番目の要素から2要素を['D1', 'D2', 'D3']で置換

$list = [
 'D1',
 'D2',
 'D3',
 'B',
 'C',
];

$list = [
 'A',
 'B',
 'C',
];
array_splice($list, -2, 2, ['D1', 'D2', 'D3']);
$listの2番目(-2)の要素から2要素を['D1', 'D2', 'D3']で置換

$list = [
 'A',
 'D1',
 'D2',
 'D3',
];

配列の切り取り

$list1 = ['A', 'B', 'C'];
Array(
  [0] => A
  [1] => B
  [2] => C
)
$list2 = array_slice($list1, 1, 2, false);

Array(
  [0] => B
  [1] => C
)
元のインデックス番号は維持されない
インデックス番号が0から降り直される

$list1 = ['A', 'B', 'C'];
Array(
  [0] => A
  [1] => B
  [2] => C
)
$list2 = array_slice($list1, 1, 2, true);

Array(
  [1] => B
  [2] => C
)
元のインデックス番号は維持される

配列の検索

$list = [
 'PHP',
 'Java',
 'JavaScript',
 'PHP',
];

$ret = array_search('Java', $list);
→1
先頭の要素番号が取得される
$ret = array_search('C#', $list);
→false

制御文で使用する場合
if (array_search('Java', $list)===false){
 
}

$list = [
 'PHP',
 'Java',
 'JavaScript',
 'PHP',
];
$ret = in_array('Java', $list);
→true
$ret = in_array('Ruby', $list);
→false

制御文で使用する場合
if (in_array('Java', $list)){
 
}

サブルーチンへの配列渡し

配列→配列
int ary[] = { 1, 2, 3, 4, 5 };

int ret = fnPlus(ary);
ret:15

int fnPlus(int p[])
{
 int sum = 0;
 for (int i = 0; i < 5; i++)
 {
  sum += p[i];
 }
 return sum;
}

配列→ポインタ
int ret = fnPlus(ary);
ret:15

int fnPlus(int *p)
{
 配列の先頭アドレスを取得
 p = &ary[0];

 
 int sum = 0;
 for (int i = 0; i < 5; i++)
 {
  sum += p[i];
 }
 return sum;
}