ネストされたMap
CoddyのDartジャーニー「論理とフロー」セクションの一部。レッスン 31/65。
単純なキーと値のペアよりも複雑な階層構造でデータを整理する必要がある場合があります。ネストしたマップを使うと、ほかのマップの値としてマップを保存でき、データを複数の階層に整理できます。
ネストされたマップとは、値自体がMapオブジェクトであるMapのことです。この構造は、複数の詳細情報を持つユーザープロフィールや、さまざまな属性を持つ商品カタログなど、カテゴリとサブカテゴリがあるデータを表すのに最適です。
Map<String, Map<String, dynamic>> userProfiles = {
'alice': {
'email': 'alice@example.com',
'age': 28
},
'bob': {
'email': 'bob@example.com',
'age': 32
}
};
print(userProfiles['alice']!['email']); // alice@example.com
print(userProfiles['bob']!['age']); // 32ネストされたマップ内のデータにアクセスするには、複数の角括弧を使います。最初の角括弧で外側のマップのキーにアクセスし、2つ目の角括弧で内側のマップのキーにアクセスします。マップの検索ではキーが存在しない場合にnullが返されるため、キーが存在すると分かっている場合、Dartでは最初の検索の後に!が必要です: userProfiles['alice']!['email']。この2階層の構造により、関連する情報を整理してアクセスしやすい状態に保ちながら、簡単にまとめることができます。
チャレンジ
簡単入れ子のマップを使用して従業員の詳細情報を保存する、会社の従業員名簿管理プログラムを作成してください。プログラムでは、次の処理を行います。
- 会社名を表す文字列入力を読み取る
- 従業員データを表す複数の入力セットを読み取る(
"employees_done"を受け取ると入力が終了します)。各従業員のデータは次のとおりです。- 従業員ID(文字列)
- 名前(文字列)
- 部署(文字列)
- 給与(整数に変換する必要がある文字列)
- 経験年数(整数に変換する必要がある文字列)
- 検索する従業員IDを表す文字列入力を読み取る
- 各従業員IDをキーとし、従業員の詳細情報を含む別のマップを値とする入れ子のMapを作成する
- 入れ子のマップアクセスを使用して、特定の従業員情報にアクセスし、表示する
- 部署ごとの統計を計算し、以下に示す正確な形式で従業員名簿のレポートを出力する
たとえば、会社名が"TechCorp Solutions"で、従業員データに、名前が"Alice Johnson"、部署が"Engineering"、給与が75000、経験年数が5の"EMP001"、名前が"Bob Smith"、部署が"Marketing"、給与が60000、経験年数が3の"EMP002"、名前が"Carol Davis"、部署が"Engineering"、給与が80000、経験年数が7の"EMP003"が含まれ、検索する従業員IDが"EMP001"の場合、プログラムは次のように出力します。
Company: TechCorp Solutions
Employee Directory: {EMP001: {name: Alice Johnson, department: Engineering, salary: 75000, experience: 5}, EMP002: {name: Bob Smith, department: Marketing, salary: 60000, experience: 3}, EMP003: {name: Carol Davis, department: Engineering, salary: 80000, experience: 7}}
Employee Lookup (EMP001):
Name: Alice Johnson
Department: Engineering
Salary: $75000
Experience: 5 years
Department Analysis:
Engineering employees: 2
Marketing employees: 1
Total employees: 3
Average salary: $71666
Status: Employee directory processed successfully会社名が"Global Industries"で、従業員データに、名前が"David Wilson"、部署が"Sales"、給与が55000、経験年数が4の"E100"、名前が"Emma Brown"、部署が"HR"、給与が65000、経験年数が6の"E101"が含まれ、検索する従業員IDが"E101"の場合、プログラムは次のように出力します。
Company: Global Industries
Employee Directory: {E100: {name: David Wilson, department: Sales, salary: 55000, experience: 4}, E101: {name: Emma Brown, department: HR, salary: 65000, experience: 6}}
Employee Lookup (E101):
Name: Emma Brown
Department: HR
Salary: $65000
Experience: 6 years
Department Analysis:
Sales employees: 1
HR employees: 1
Total employees: 2
Average salary: $60000
Status: Employee directory processed successfully会社名が"StartupHub"で、従業員データに、名前が"Frank Miller"、部署が"Development"、給与が70000、経験年数が2の"S001"、名前が"Grace Lee"、部署が"Design"、給与が58000、経験年数が3の"S002"、名前が"Henry Chen"、部署が"Development"、給与が72000、経験年数が4の"S003"、名前が"Ivy Taylor"、部署が"Marketing"、給与が62000、経験年数が5の"S004"が含まれ、検索する従業員IDが"S003"の場合、プログラムは次のように出力します。
Company: StartupHub
Employee Directory: {S001: {name: Frank Miller, department: Development, salary: 70000, experience: 2}, S002: {name: Grace Lee, department: Design, salary: 58000, experience: 3}, S003: {name: Henry Chen, department: Development, salary: 72000, experience: 4}, S004: {name: Ivy Taylor, department: Marketing, salary: 62000, experience: 5}}
Employee Lookup (S003):
Name: Henry Chen
Department: Development
Salary: $72000
Experience: 4 years
Department Analysis:
Development employees: 2
Design employees: 1
Marketing employees: 1
Total employees: 4
Average salary: $65500
Status: Employee directory processed successfullyプログラムでは、外側のマップで従業員IDをキーとして使用し、各値が"name"、"department"、"salary"、"experience"をキーとして含む内側のマップとなる、入れ子のMap構造を作成してください。二重の角括弧を使用した入れ子のマップアクセスで、特定の従業員情報を取得してください。部署ごとの従業員数を数え、給与の合計を従業員数で割って平均給与を計算してください。入力形式は、会社名、続いて5つの値(従業員ID、名前、部署、給与、経験年数)のセットを"employees_done"が入力されるまで、その後に検索する従業員IDとなります。
自分で試してみよう
import 'dart:io';
void main() {
// 会社名を読み込む
String? companyName = stdin.readLineSync();
// 従業員ディレクトリ用の入れ子のマップを初期化する
Map<String, Map<String, dynamic>> employeeDirectory = {};
// "employees_done" が入力されるまで従業員データを読み込む
while (true) {
String? input = stdin.readLineSync();
if (input == "employees_done") {
break;
}
String employeeId = input!;
String? name = stdin.readLineSync();
String? department = stdin.readLineSync();
String? salaryStr = stdin.readLineSync();
String? experienceStr = stdin.readLineSync();
// 給与と経験年数を整数に変換する
int salary = int.parse(salaryStr!);
int experience = int.parse(experienceStr!);
// TODO: 各従業員の入れ子のマップ構造を作成し、ディレクトリに追加する
}
// 検索する従業員IDを読み込む
String? lookupId = stdin.readLineSync();
// TODO: 以下の処理を行うコードを記述する:
// 1. 会社名と従業員ディレクトリを表示する
// 2. 指定された従業員の情報を検索して表示する
// 3. 部門ごとの統計を計算する
// 4. 平均給与を計算する
// 5. 完全なレポートを指定された形式で出力する
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
論理とフローのすべてのレッスン
1リスト操作の応用
リストのプロパティ: first と lastリストの状態: isEmpty と isNotEmptyリストの反転リストへの追加: insertリストの削除: removeWhereリスト内の検索: indexOfリストのソートリストのシャッフルまとめ - リストオーガナイザー自分で練習してみよう: Dartオンラインコンパイラ