Closed8

Flutter & Dart Cookbookの読書メモ(第4章)

marbullmarbull

Handling Lists and Maps

本章では、Dartによるデータ操作の基礎について概説します。この章の目的は、Dartで情報を扱うための基礎的なデータ構造を提供するために使用されるリストとマップをカバーすることです。

もしあなたが他の言語に精通しているのであれば、紹介されている多くの概念は馴染みがあるはずです。しかし、これらのテクニックを初めて目にする人のために、コードの例は自己完結しています。例題を実行し、実験することで、この言語の仕組みを理解するのに役立つと思われます。

この章では、まずリストについて説明します。リストは、オブジェクトを保持するために使用されるインデックス可能なデータ構造です。リストは、様々なシナリオで使用することができるため、Dartでは非常に一般的な要素です。

また、キーと値のペアを扱うのに便利なマップの使用方法についても説明します。キーと値のペアは、キーが値にアクセスするためのインデックスとして使用される連想関係です。例えば、キーが数字で、値が数字から派生する年の月のデータ構造があります。

この章では、アプリケーションでマップとリストを使用する方法を学びます。

marbullmarbull

4.1 Creating Lists of Data

  • Problem
    Dartアプリケーションの中で値のリストを使用する方法が欲しい。
  • Solution
    リストを使って、オブジェクトを順序のあるコレクションとして整理することができます。リストは、情報を保持することができる配列オブジェクトを表します。リストには、ゼロインデックスでグループ化された要素が含まれており、シンプルな構成になっています。

以下は、DartにおけるListの使用例です。

void main() {
  List listMonths = ['January', 'February', 'March'];

  listMonths.forEach(print);
}
  • Discussion
    リストは非常に汎用性が高く、様々な状況で使用することができます。先ほどの例では、リストクラスを使って、その年の月を保持しています。

List宣言はStringを保持するために使用されていますが、実際には様々なデータ型を保持することができ、このオブジェクトは非常に柔軟です。リストクラスには、forEach、length、reverse、isEmpty、isNotEmpty などの便利なメソッドが用意されています。リスト内の各要素は直接アドレス指定が可能で、forEach メソッドを介してアクセスすることもできます。

リストは、開始と終了の角括弧で示されます。角括弧の中には、カンマで区切られたリストの要素が入ります。リストの項目は、宣言時に初期化したり、処理中に後で修正したりすることができます。

リストの長さはメソッドとして利用可能で、これは現在利用可能な要素の数を識別するために使用されます。リストはゼロから始まるので、手動で要素にアクセスする場合は、最初の要素を取得するためにゼロを使用する必要があることに注意してください。

リストのもう一つの良い特徴は、情報を処理するための様々なメソッドを含んでいることです。この例では、forEachメソッドを使って、リストに含まれる要素のprint文を実行しています。

Dartに慣れてくると、Listはアプリケーションを書く上で欠かせないツールの1つになるでしょう。

marbullmarbull

4.2 Amending a List of Data

  • Problem
    既存のリストに新しいコンテンツを追加したい。
  • Solution
    リストに新しいコンテンツを組み込むには、リスト追加メソッドを使用します。リストは、新しい要素の動的な追加をサポートしており、必要に応じて拡張することができます。

以下は、Dart で List 要素を追加する方法の例です。

void main() {
  List listMonths = ['January', 'February', 'March'];

  listMonths.add('April');

  listMonths.forEach(print);
}
  • Discussion
    先ほどの例では、最初に3つの要素からなるListが定義されています。もし、要素の数を増やしたい場合は、Listのaddメソッドを使用することで可能です。add メソッドは、List の最後に新しい要素を追加します。

新しい要素を追加する際には、List クラスが関連するすべての処理を行います。add メソッドは、渡された情報をどのように追加するかを知っており、関連するクラスのプロパティ (例: 長さ) が更新されるようにします。したがって、この例では、月が "January", "February", "March", "April" と出力されているのがわかるでしょう。また、4つ目の項目が追加されたことを反映して、Listの長さが修正されていることがわかります。

リストは動的な性質を持っているため、データ構造の汎化が必要な様々な状況に対応できます。リストは、様々なデータ型を扱うために、様々な場面で使用されています。

marbullmarbull

4.3 Using Lists with Complex Types

  • Problem
    Stringsとintergerの組み合わせでListを作り、新しい複合データ型を作りたい。
  • Solution
    他のデータ型の連結を整理するために、リストを使用します。リストは、マップのような他のデータ構造を扱うのに特に有効です。

以下は、Dartで複雑なデータ型を持つListを使用する例です。

void main() {
  Map<String, dynamic> filmStarWars = {"title": "Star Wars", "year": 1977};
  Map<String, dynamic> filmEmpire = {"title": "The Empire Strikes Back", "year": 1980};
  Map<String, dynamic> filmJedi = {"title": "The return of the Jedi", "year": 1983};

  List listFilms = [filmStarWars, filmEmpire, filmJedi];

  Map<String, dynamic> currentFilm = listFilms[0]; 

  print(currentFilm);
  print(currentFilm['title']);
}
  • Discussion
    この例では、タイトルと年号の情報を囲むMapに映画データを追加している。ここでは、個々のMapを管理するためにListを使用し、個々の要素を組み合わせることができるようにしています。その結果、Listは格納される情報にアクセスするための便利なデータ構造となる。

リスト内の情報へのアクセスは、通常のリストと同じ処理になります。情報にアクセスするには、変数をデリファレンスする必要があります。この文脈では、参照解除のために、インデックスを使用して、プロパティ値にアクセスすることをDartに伝えます。listFilms[0]は、Listの最初の要素にアクセスすることを意味します。

Listにアクセスできれば、あとは関連するデータ型に基づいてアクセスすることができます。このコード例では、Mapを使用して複数の値をまとめています。各要素がMapであるため、これに関連するデータを取得することができます。参照解除された値を使用して、新しい変数 currentFilm に格納します。この変数は、直接またはキーを使用してアクセスすることができます。

リストを使用することで、複雑なデータ型に一貫した方法でアクセスすることができます。データ型を調整する必要がある場合は、リストを使用することで、このプロセスをより管理しやすくすることを検討してください。

marbullmarbull

4.4 Handling Map Key/Value Pairings

  • Problem
    Dartアプリケーションで、キーと値のペアを処理したい。
  • Solution
    Mapを使用して、任意の型のキー/値オブジェクトを処理します。Mapのキーは、Mapの値にアクセスするためのインデックスとして機能するため、一意であることが要求されます。Mapの値は一意である必要はなく、必要に応じて複製することができます。

以下は、DartでMapを宣言する方法の例です。

void main() {
  Map<int, String> mapMonths = {0: 'January', 1: 'February', 2: 'March'};
  Map<int, String> moreMonths = {3: 'April', 4: 'May'};

  mapMonths.addEntries(moreMonths.entries);
  
  mapMonths.forEach((key, value) {
    print('$key: $value');
  });
}
  • Discussion
    コード例では、月情報をもとにしたデータの集まりを定義するためにMapを使用しています。この種の構成は、キーと値の解析が有効な情報の断片を一緒に組み合わせることができるため、非常に便利です。

Mapの構造は、JavaScript Ocject Notation(JSON)などのリスト情報を処理する際に非常に有効である。

Mapの宣言は、標準的な変数の書式に従う。注:Mapは実際には関数呼び出しなので、これには中括弧の付加が必要である。この例では、Map は整数と文字列で構成されることを示し、キー(すなわちインデックス)に数値が使用されることを意味します。文字列の値フィールドは、月への参照を保持します。また、この値をダイナミックに定義することで、さまざまなタイプの変数を使用できるようになり、さらに柔軟性が増します。より具体的には、文字列を明示的に置き換える動的な定義を導入することができます。このように変更すると、Dartは変数の割り当てに基づいて正しいデータ型を自動的に推論します。

Map に値を入れるには、キー (例: mapManth) を定義し、値 (例: January) を割り当てます。値の代入はどのような順序でも構いません。重要なのは、使用するキーが重複しないように注意することです。

Mapに要素を追加するには、キーと値の両方が必要です。この例では、aprilMonthという追加のMap構造体が作成されている。新しい月 Map のパラメータを指定して addEntries メソッドを呼び出し、既存の構造体に新しい月を追加します。

Mapクラス内の情報にアクセスするには、Mapメソッドとプロパティを使用します。Map には、関連するデータ項目にアクセスするために使用できるメソッドがいくつか用意されています。各項目をループで処理するには、キーを使用して個々の項目にアクセスします。この例では、Map forEach メソッドを使用して、各データ構造アイテムにアクセスしています。キーにアクセスすることで、これらの要素を組み合わせてMapに関連する情報を取得することができます。

データへのアクセスに関しては、Dartチームが提供するスタイルガイド情報を常に確認する価値があります。この例では、forEachを使用するのではなく、forループを使用することもできます。アクセスに関連するガイダンスは、Dartのドキュメントで定義されています。

Dart言語が成熟し、ガイドラインが変更された場合、その理由を理解できるようにすることは良いことです。開発者としての一般的なアドバイスは、これらの変更を常に意識し、後の開発段階においてより複雑なリファクタリングを避けるために、一般的なガイダンスに対応することを検討することです。

marbullmarbull

4.5 Printing Map Data Structure Content

  • Problem

Mapデータ変数の値を出力したい。

  • Solution

Mapを使用して、インデックス付きの項目を参照する。Mapの値はキーと値の組み合わせとして参照され、変数に代入することで簡単にアクセスできるようになる。

以下は、DartでMapのプロパティを取得し、その値を出力する例です。

void main() {
  Map<int, String> mapMonths = {0: 'January', 1: 'February', 2: 'March'};

  print("Month: ${mapMonths[0]}");
  print("Map: $mapMonths");
}
  • Discussion

このコード例では、Map構造体内の値にアクセスするため、Mapのインデックスを作成するためのキーを提供し、目的の値を取得する。最初のprint文は、キー[0]に関連する情報を明示的に要求しています。変数の周りに中括弧を使用することは、月の値を確実に出力するために必要です。 2つ目のprint文では、mapMonths変数に対してMap全体を出力しています。

このコード例では、Map構造体内の値にアクセスするため、Mapのインデックスを作成するためのキーを提供し、目的の値を取得する。最初のprint文は、キー[0]に関連する情報を明示的に要求しています。変数の周りに中括弧を使用することは、月の値を確実に出力するために必要です。 2つ目のprint文では、mapMonths変数に対してMap全体を出力しています。

値を保持するために個別の変数を作成したくない場合は、Mapの値を参照解除することを思い出してください。print文の中括弧は、DartコンパイラにMapの内容ではなく、変数の値が必要であることを示すために追加されています。

marbullmarbull

4.6 Varidating That Content Exists in a Map

  • Problem

Mapのインデックス機能を利用して、キーが明示的に存在するかどうかを特定する。

以下は、Dartを使用してMapにキーが存在するかどうかを検証する例です。

void main() {
  Map<int, String> mapMonths = {0:  'January', 1: 'February', 2: 'March'};

  if (mapMonths[0] != null) {
    print('Test 1: key exists');
  }

  if (mapMonths.containsKey(2)) {
    print('Test 2: key exists');
  }
}
  • Discussion

マップはキー値で索引付けされているので、キーの存在の検証もすぐに行える。キーを見つけるには、必要なキーを使ってMapのインデックスを作成する。

この例では、キーがMapに存在しない場合、Mapはnull値を返します。値が存在するかどうかを確認するために、NULLでない値を返すかどうかを明示的にチェックすることができます。別のチェック方法としては、containsKey メソッドを使用して、値が存在するかどうかを確認することもできます。機能的な観点からは、if文は同じチェックを実行していることになります。

スタイリッシュに、あるアプローチを好むかもしれません。キーがマップに存在する場合、返される情報はそのキーに関連付けられた値になります。

marbullmarbull

4.7 Printing Complex Data Types

  • Problem

複雑なデータ型に基づいた変数を出力したい。

  • Solution

アプリケーションからの情報を表示するには、printステートメントを使用します。print文は、表示するデータ型を正しく補間するように書式設定する必要があります。

ここでは、複雑なデータ型を表示する方法の例を示します。

import 'dart:convert';

void main() {
  // Create JSON value
  Map<String, dynamic> data = {
    jsonEncode('title'): json.encode('Star Wars'),
    jsonEncode('year'): json.encode(1977)
  };

  // Decode the JSON
  Map<String, dynamic> items = json.decode(data.toString());

  print(items);
  print(items['title']);
  print("This is the title: $items['title']");
  print('This is the title: ${items['title']}');
}
  • Discuttion

print文の中で変数を参照するには、文字を使用します。変数の前にを付けると、Dartに変数が使用されており、この値を置き換える必要があることを知らせます。

次の2つのprint文の例は、変数の値が正しく表示されるためにちょっとした助けが必要な場合に遭遇する使用例です。

最初の例では、中括弧を使わずに文字列の補間を行います。

print("This is the title: $items['title']");

2つ目の使用例では、中括弧を使った文字列補間があります。

print('This is the title: ${items['title']}');

前の文は同等に見えますが、そうではありません。最初のprintステートメントでは、Dartは表示するvarableをitemsと解釈します。変数を正しく表示するためには、実際には2行目のように中括弧で囲む必要があります。こうすることで、items['title']に関連付けられた値が正しく解釈されるようになります。

このスクラップは2023/02/14にクローズされました