22. 配列¶
動的配列クラス Array
の基本的な使い方を学びます。
22.1 Array¶
- Siv3D では
Array<Type>
で動的配列を扱います Array
はstd::vector
と同等の機能を提供するほか、追加のメンバ関数を持ちますstd::vector
のように要素がメモリ上に連続していることが保証されています
// int32 型の値を格納する配列
Array<int32> a = { 10, 20, 30, 40, 50 };
// double 型の値を格納する配列
Array<double> b = { 1.1, 2.2, 3.3, 4.4, 5.5 };
// String 型の値を格納する配列
Array<String> c = { U"Apple", U"Bird", U"Cat", U"Dog" };
22.2 配列の作成¶
- 配列は次のような方法で作成します
- 空の配列を作成
- リストから配列を作成
- 個数 × 値 で配列を作成
- 個数 × デフォルト値で配列を作成
Array<int32> v(5);
は 5 個の 0 で初期化された配列を作成しますArray<double> v(5);
は 5 個の 0.0 で初期化された配列を作成しますArray<String> v(5);
は 5 個の空文字列で初期化された配列を作成します
# include <Siv3D.hpp>
void Main()
{
// パターン ①: 空の配列を作成
{
Array<int32> v;
Print << v;
}
// パターン ②: リストから配列を作成
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v;
}
// パターン ③: 個数 × 値 で配列を作成
{
Array<int32> v(5, -5);
Print << v;
}
// パターン ④: 個数 × デフォルト値で配列を作成
{
Array<int32> v(5);
Print << v;
}
while (System::Update())
{
}
}
22.3 要素数の取得¶
.size()
は配列の要素数をsize_t
型で返します
# include <Siv3D.hpp>
void Main()
{
Array<int32> v1 = { 10, 50, 30, 20, 40 };
Print << v1.size();
Array<int32> v2;
Print << v2.size();
while (System::Update())
{
}
}
22.4 空であるかを調べる(1)¶
.isEmpty()
は配列が空であるか(要素数が 0 であるか)をbool
型で返します
# include <Siv3D.hpp>
void Main()
{
Array<int32> v1 = { 10, 50, 30, 20, 40 };
Print << v1.isEmpty();
Array<int32> v2;
Print << v2.isEmpty();
while (System::Update())
{
}
}
22.5 空であるかを調べる(2)¶
if (配列)
を使って配列が空であるかを調べます- 配列が空である場合、配列は
false
と評価されます
# include <Siv3D.hpp>
void Main()
{
Array<int32> v1 = { 10, 50, 30, 20, 40 };
if (v1)
{
Print << U"v1 is not empty";
}
Array<int32> v2;
if (not v2)
{
Print << U"v2 is empty";
}
while (System::Update())
{
}
}
22.6 末尾への要素追加¶
v << x;
で配列v
の末尾に要素x
を追加しますstd::vector
の.push_back(x)
を短く書けるようにしたものです- 配列の末尾への追加は、それ以外の場所(先頭や途中)への追加に比べて最も効率的です
# include <Siv3D.hpp>
void Main()
{
Array<int32> v;
v << 10;
v << 50;
v << 30;
Print << v;
v << 20 << 40;
Print << v;
while (System::Update())
{
}
}
22.7 末尾の要素の削除¶
.pop_back()
で配列の末尾の要素を削除します- 要素数が 0 のときに呼び出してはいけません
- 事前に要素数が 0 でないことを確認してください
- 配列の末尾の要素の削除は、それ以外の場所(先頭や途中)の要素の削除に比べて最も効率的です
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v;
v.pop_back();
Print << v;
v.pop_back();
Print << v;
while (v)
{
v.pop_back();
}
Print << v;
while (System::Update())
{
}
}
22.8 すべての要素の削除¶
.clear()
で配列のすべての要素を削除し、空の配列にします- 要素数が 0 のときに呼び出しても問題ありません(何もしません)
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v;
v.clear();
Print << v;
while (System::Update())
{
}
}
22.9 要素数の変更¶
.resize(n)
で配列の要素数をn
に変更します- 要素数が増える場合、新しい要素はデフォルト値で初期化されます
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v;
v.resize(3);
Print << v;
v.resize(5);
Print << v;
while (System::Update())
{
}
}
22.10 範囲 for 文による配列走査(const 参照)¶
- 範囲 for 文を使って配列の要素を走査します
- 各要素へのアクセスは、通常は const 参照で行います
- 範囲 for 文の中で、対象の配列のサイズを変更する操作は行わないでください
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
for (const auto& elem : v)
{
Print << elem;
}
while (System::Update())
{
}
}
22.11 範囲 for 文による配列走査(参照)¶
- 範囲 for 文を使って配列の要素を走査します
- ループ内で要素を変更する場合、const 参照の代わりに参照を使って要素にアクセスします
- 範囲 for 文の中で、対象の配列のサイズを変更する操作は行わないでください
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
for (auto& elem : v)
{
elem *= 2;
}
Print << v;
while (System::Update())
{
}
}
22.12 指定したインデックスの要素へのアクセス¶
[i]
で配列のi
番目の要素にアクセスしますi
は 0 から数えます。有効なインデックスは0
から.size() - 1
までです
- 範囲外にアクセスしてはいけません
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v[0];
Print << v[4];
v[1] = 500;
Print << v;
while (System::Update())
{
}
}
22.13 先頭・末尾の要素へのアクセス¶
.front()
は先頭の要素への参照を返しますv[0]
と同じです
.back()
は末尾の要素への参照を返しますv[v.size() - 1]
と同じです
- いずれも要素数が 0 のときに呼び出してはいけません
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v.front();
Print << v.back();
v.front() = 100;
v.back() = 400;
Print << v;
while (System::Update())
{
}
}
22.14 先頭・終端位置のイテレータ取得¶
.begin()
は先頭位置のイテレータを返します.end()
は終端位置のイテレータを返します
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
auto it = v.begin();
Print << *it;
++it;
Print << *it;
while (System::Update())
{
}
}
22.15 その他の挿入・削除操作¶
.push_front(値)
で、先頭に要素を追加します.pop_front()
で、先頭の要素を削除します.insert(イテレータ, 値)
で、指定したイテレータの位置に要素を挿入します.append(配列)
で、別の配列を末尾に追加します.erase(イテレータ)
で、指定したイテレータの位置の要素を削除します.erase(イテレータ1, イテレータ2)
で、指定した範囲の要素を削除します- 先頭や途中への要素の挿入・削除は、それ以降の既存要素の移動を伴うため、うしろの要素数に比例したコストがかかります
- 通常は避けるか、小さい配列でのみ使用するべきです
# include <Siv3D.hpp>
void Main()
{
{
Array<int32> v = { 10, 20, 30, 40, 50 };
v.push_front(5);
Print << v;
v.pop_front();
Print << v;
}
{
Array<int32> v = { 10, 20, 30, 40, 50 };
v.insert((v.begin() + 2), 25);
Print << v;
}
{
Array<int32> v1 = { 10, 20, 30 };
Array<int32> v2 = { 40, 50 };
v1.append(v2);
Print << v1;
}
{
Array<int32> v = { 10, 20, 30, 40, 50 };
v.erase(v.begin() + 2);
Print << v;
v.erase(v.begin(), (v.begin() + 2));
Print << v;
}
while (System::Update())
{
}
}
出力
{5, 10, 20, 30, 40, 50}
{10, 20, 30, 40, 50}
{10, 20, 25, 30, 40, 50}
{10, 20, 30, 40, 50}
{10, 20, 40, 50}
{40, 50}
22.16 条件を満たす要素の削除(イテレータ方式)¶
- イテレータによるループを利用して、条件を満たす要素を削除するには次のようにします
配列から 30 未満の要素を削除する
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
for (auto it = v.begin(); it != v.end();)
{
if (*it < 30)
{
it = v.erase(it);
}
else
{
++it;
}
}
Print << v;
while (System::Update())
{
}
}
22.17 条件を満たす要素の削除(.remove_if()
方式)¶
.remove_if(条件を記述した関数)
で、条件を満たす要素を削除します- イテレータ方式よりも簡潔に書けます
- 「条件を記述した関数」は、要素を引数(値渡しまたは const 参照渡し)で受け取り
bool
を返す関数オブジェクトです- 関数やラムダ式を使います
# include <Siv3D.hpp>
void Main()
{
{
Array<int32> v = { 11, 22, 33, 44, 55 };
// 偶数の要素を削除する
v.remove_if(IsEven);
Print << v;
}
{
Array<int32> v = { 10, 50, 30, 20, 40 };
// 30 未満の要素を削除する
v.remove_if([](int32 x) { return x < 30; });
Print << v;
}
while (System::Update())
{
}
}
22.18 配列のソート¶
.sort()
で配列を昇順にソートします.rsort()
で配列を降順にソートします
# include <Siv3D.hpp>
void Main()
{
{
Array<int32> v = { 10, 50, 30, 20, 40 };
v.sort();
Print << v;
}
{
Array<String> v = { U"Bird", U"Dog", U"Apple", U"Cat" };
v.rsort();
Print << v;
}
while (System::Update())
{
}
}
22.19 配列の逆順¶
.reverse()
で配列を逆順にします
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
v.reverse();
Print << v;
while (System::Update())
{
}
}
22.20 配列の要素のシャッフル¶
.shuffle()
で配列の要素をシャッフルします
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 1, 2, 3, 4, 5, 6 };
v.shuffle();
Print << v;
while (System::Update())
{
}
}
22.21 配列の要素の合計¶
.sum()
で配列の要素の合計を計算します
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
Print << v.sum();
while (System::Update())
{
}
}
22.22 すべての要素に同じ値を代入¶
- .fill(値) で、すべての要素に同じ値を代入します
# include <Siv3D.hpp>
void Main()
{
Array<int32> v = { 10, 50, 30, 20, 40 };
v.fill(100);
Print << v;
while (System::Update())
{
}
}
22.23 すべての要素に関数を適用した結果の取得¶
.map(関数)
で、すべての要素に関数を適用した結果の配列を得ます- 関数は、要素を引数にとり、変換後の要素を返す関数オブジェクトです